Le lundi 19 mars 2007 17:25, Paul a ñÄrit > Hi there. I am having a bit of trouble trying to solve a particular > sorting problem with an array of data. > > Please bear with me for a moment regarding the setup of this problem. > I don't currently have any control over the input data. I am just > trying to format the report of this data as per the requirement. > > I have the following sample array data to work with: > @date_array = [['2/22/07','1:03 pm'],['3/9/07','10:45 pm'], > ['3/1/07','1:52 pm'],['3/13/07','2:00 pm'],['2/28/07','10:45 am'], > ['3/5/07','4:00 pm'],['2/14/07','5:00 pm'],['3/9/07','10:18 am'], > ['3/13/07','11:15 am']] > > (The actual array contains more data, but this is good enough to work > on this problem. BTW, date format = mm/dd/yy.) > > Requirement: > 1) Sort in descending order by Date (i.e. @date_array[x][0] ) > 2) Sort in ascending order by Time (i.e. @date_array[x][1] ) > > Elsewhere in the script, I use the following line to sort by a > > particular element in a row: > > @fields.sort! { |a,b| b[ x ] <=> a[ x ] } # i.e. descending sort > > This works quite nicely for string and numeric fields, but *not* for > Date or Time string fields. As an example, when I try it with the > above data I get the following: > ---- > puts 'Descending Sort - By Date:' > @date_array.sort! { |a,b| b[ 0 ] <=> a[ 0 ] } > @date_array.each_index do |row| > puts "row # #{row} = " + @date_array[row].join(" : ") > end > ---- > Descending Sort - By Date: > row # 0 = 3/9/07 : 10:18 am > row # 1 = 3/9/07 : 10:45 pm > row # 2 = 3/5/07 : 4:00 pm > row # 3 = 3/13/07 : 2:00 pm > row # 4 = 3/13/07 : 11:15 am > row # 5 = 3/1/07 : 1:52 pm > row # 6 = 2/28/07 : 10:45 am > row # 7 = 2/22/07 : 1:03 pm > row # 8 = 2/14/07 : 5:00 pm > ---- > > --> Which is a nice string sort again, but not a date sort. > > I know I'll have to write a method to deal with these two columns of > data, but I'm not sure where to start. I've tried googling solutions > in both this discussion group and the internet but so far haven't > turned up anything I can use. > > Suggestions? Hi Paul, You may want to first convert your dates/times to real Time objects, so that they can be compared. Here is my solution : require 'pp' pp @date_array.sort_by {|ary| ary.map{|elt| Time.parse(elt) } } [["2/14/07", "5:00 pm"], ["2/22/07", "1:03 pm"], ["2/28/07", "10:45 am"], ["3/1/07", "1:52 pm"], ["3/5/07", "4:00 pm"], ["3/9/07", "10:18 am"], ["3/9/07", "10:45 pm"], ["3/13/07", "11:15 am"], ["3/13/07", "2:00 pm"]] => nil A quick explanation : @date_array is sorted with sort_by, because we want to sort the array according to a simple criteria. For the comparison, each element of the array (ie the date and the time string) is converted to a Time object with Time#parse, and is kept in an array (this is why I used #map). Doing so, the original arrays of Strings will be sorted, according to the order of the Arrays containing the real Time objects. For example on a single element of your original array : ["2/14/07", "5:00 pm"].map{|el| Time.parse(el)} => [Wed Feb 14 00:00:00 +0100 2007, Mon Mar 19 17:00:00 +0100 2007] Instead of comparing arrays that contains one element for the date and another element for the time, we could have created only one Time object representing both : @date_array.sort_by {|ary| Time.parse("#{ary.first} #{ary.last}") } Regards. -- Olivier Renaud