views:

241

answers:

8

I have this months array:

["January", "March", "December" , "October" ]

And I want to have it sorted like this:

["January", "March", "October", "December" ] 

I'm currently thinking in a "if/else" horrible cascade but I wonder if there is some other way to do this.

The bad part is that I need to do this only with "string" ( that is, without using Date object or anything like that )

What would be a good approach?

+3  A: 

Have an array with the proper sort, and sort based on it.

Another solution (if your language supports it) is to have an associative array from month names to numbers (1..12) and use a custom comparator running sort on your array.

Solution in Perl :D

my @mon = qw( January February March April May June July August September October November December );
my $mon;
@{$mon}{@mon} = (0..$#mon);

sub by_month {
    $mon->{$a} <=> $mon->{$b};
}

sort by_month @data_to_sort

(although I'm sure a golfer could do that in < 30 characters)

And here's a solution in plain C : http://www.pnambic.com/CPS/SortAnal/html/MonOrder.html

Kornel Kisielewicz
+1 very elegant solution!
jspcal
+1 Could you post something a bit more algorithmic?
OscarRyz
Considering that you have a named set of elements, the only way to make it more algorithmic would be to use hacks based on hashing :> -- e.g. find a hash that for the month names gives increasing values.
Kornel Kisielewicz
+8  A: 

Create a table with name->index, then sort the array based on its value in the table.

A couple of examples may be useful, in C# arr.sort(myCompare), in Java Collections.sort(arr, myCompare), in Python arr.sort(myCompare), in PHP usort($arr, 'myCompare'), in C++ sort(vec.begin(), vec.end(), myCompare).

jspcal
Gets my vote. Map each month to an index then quicksort
zebrabox
I'm ok with the first part ( create the name-index ) about the second, "sort the array based.." I'm a little confused.
OscarRyz
are you serious? quicksort won't do any good for such scale.
Dyno Fu
Sure, I wanna see that coded in C
Kornel Kisielewicz
@Oscar, it's basically what I wrote in my answer above as "another solution". If you'd name the language, it'd be easier.
Kornel Kisielewicz
@Kornel Kisielevicz: mhmmm it's PBL :( Python, Ruby or pretty much any other will do ( as long it doesn't use language specific functions ) I think I almost have it.
OscarRyz
+1  A: 

For something like months, I'd just hard-code the arrays I needed...

It's not like months are gonna change any time soon.

Rudiger
Month names would change if you had to support a language other than English...
Richard Ev
+5  A: 

If I had a way to supply a custom sorting order, I'd create a list defining the correct order:

correct = List("January", "February", "March", ...)

And then sort by the position in that list, something like:

toSort.sort(a, b) => compare(correct.index(a), correct.index(b))
Fabian Steeg
A: 

Add a prefix for each month:


Jan -> aJan
Feb -> bFeb
...

Sort, then remove the prefix.

Dyno Fu
A: 

Create a mapping:

month_map = {"January":1,
             "February":2,
             "March":3,
             "April":4} # etc..

Use the mapping to compare one month to the other.

OR

Most languages/frameworks have objects for handling dates. Create date objects for all the months and compare them using the native (if available) inequality operators or basic sorting functions:

import datetime
January  = datetime.date(2010,1,1)
February = datetime.date(2010,2,1)
if February < January: print("The world explodes.")
pokstad
A: 

Thanks all for the suggestions, I would like to mark you all as accepted.

Here's the resulting code:

// correct order 
months as String[] = ["jan", "feb", "mar", "apr", "may", "jun",
                      "jul", "aug", "sep", "oct", "nov", "dec"]
// my unsorted months 
myMonths as String[] = ["mar", "dec", "jul", "jan", "sep"]

// poor substitute for Map
mappedIndex as Int[]

// create an array with the corresponding index 
for each m in myMonths do
    i as Int = 0;
    for each month in months do 
       if m == month then 
           mappedIndex[] = i // no break, so I should use "else"
       else
          i = i + 1
       end
    end
end

// At this point mapped index has the same order as my "unsorted" array
// in this case [2,11,5,0,8]

// Fortunately this language has "sort" otherwise I would jump out of the window
mappedIndex.sort()

// create a new array to hold the sorted values
myMonthsSorted as String[]

// and fill it with the correct value
for each i in mappedIndex do 
   myMonthsSorted[] = months[i]
end
OscarRyz
+1  A: 

Talking from a Java POV, I'm going to pimp (as I often do) google-collections (soon to be replaced with Guava):

Arrays.sort(myMonths, Ordering.explicit("Jan", "Feb", "Mar", ....));

... and you're done.

Don't write it yourself if someone else has done it, probably more efficiently and with a nicer API than you probably would.

Not helpful in the general case, but just in case any Java folk have the same problem...

Cowan
Unfortunately I don't have access to java here. Otherwise I would've used `SimpleDateFormat.parse` + custom `Comparable` implementation
OscarRyz