简体   繁体   中英

Sorting an array of hashes by a date field

I have an object with many arrays of hashes, one of which I want to sort by a value in the 'date' key.

 @array['info'][0] = {"name"=>"personA", "date"=>"23/09/1980"}
 @array['info'][1] = {"name"=>"personB", "date"=>"01/04/1970"}
 @array['info'][2] = {"name"=>"personC", "date"=>"03/04/1975"}

I have tried various methods using Date.parse and with collect but an unable to find a good solution.

Edit: To be clear I want to sort the original array in place

    @array['info'].sort_by { |i| Date.parse i['date'] }.collect

How might one solve this elegantly the 'Ruby-ist' way. Thanks

Looks fine overall. Although you can drop the collect call since it's not needed and use sort_by! to modify the array in-place (instead of reassigning):

@array['info'].sort_by! { |x| Date.parse x['date'] }

Another way, which doesn't require converting the date strings to date objects, is the following.

Code

def sort_by_date(arr)
  arr.sort_by { |h| h["date"].split('/').reverse }
end

If arr is to be sorted in place, use Array#sort_by! rather than Enumerable#sort_by .

Example

arr = [{ "name"=>"personA", "date"=>"23/09/1980" },
       { "name"=>"personB", "date"=>"01/04/1970" },
       { "name"=>"personC", "date"=>"03/04/1975" }]

sort_by_date(arr)
  #=> [{ "name"=>"personB", "date"=>"01/04/1970" },
  #    { "name"=>"personC", "date"=>"03/04/1975" },
  #    { "name"=>"personA", "date"=>"23/09/1980" }]

Explanation

For arr in the example, sort_by passes the first element of arr into its block and assigns it to the block variable:

h = { "name"=>"personA", "date"=>"23/09/1980" }

then computes:

a = h["date"].split('/')
  #=> ["23", "09", "1980"]

and then:

b = a.reverse
  #=> ["1980", "09", "23"]

Similarly, we obtain b equal to:

["1970", "04", "01"]

and

["1975", "04", "03"]

for each of the other two elements of arr .

If you look at the docs for Array#<=> you will see that these three arrays are ordered as follows:

["1970", "04", "01"] < ["1975", "04", "03"] < ["1980", "09", "23"]

There is no need to convert the string elements to integers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM