Neil
Neil

Reputation: 5178

Ruby: Sort Dates by their closeness to some test date

I have an array of dates. I need to sort those dates by their closeness to some test_date. The dates in the array can be before or after that test_date.

My simple ruby program isn't getting it right. My strategy is to convert each Date to a unix timestamp. Then I do a custom sort by the absolute value of the difference between the dates and the test_date.

Here is that program:

require 'date'
test_date = DateTime.new(2017,2,3,4,5,6)

date1 = Date.new(2017,1,6)
date2 = Date.new(2017,1,5)
date3 = Date.new(2017,2,5)
date4 = Date.new(2017,2,6)
date5 = Date.new(2017,2,9)
date6 = Date.new(2017,2,1)
date7 = Date.new(2017,2,2)

dates_ary = date1, date2, date3, date4, date5, date6, date7

sorted_dates = dates_ary.sort do |d1, d2|
    if( (d1.to_time.to_i - test_date.to_time.to_i).abs <= (d2.to_time.to_i - test_date.to_time.to_i).abs)
        d1 <=> d2
    else
        d2 <=> d1
    end
end

puts "expected order: "
puts "2017-02-02"
# pointed out in comments that 2017-02-05 will be closer than 2017-02-01 due to test_date having present hours, minutes, and seconds.
puts "2017-02-05"
puts "2017-02-01"
puts "2017-02-06"
puts "2017-02-09"
puts "2017-01-06"
puts "2017-01-05"
puts ''

puts 'actual order:'
sorted_dates.each {|d| puts d}

Also: if there is some existing ruby or rails method that sorts dates by their closeness to another date, let me know. Thanks!

Upvotes: 0

Views: 209

Answers (1)

Danil Speransky
Danil Speransky

Reputation: 30453

The if is redundant. Ruby will handle it:

sorted_dates = dates.sort do |d1, d2|
  (d1.to_time.to_i - test_date.to_time.to_i).abs <=> (d2.to_time.to_i - test_date.to_time.to_i).abs
end

Better:

sorted_dates = dates.sort_by do |date|
  (date.to_time.to_i - test_date.to_time.to_i).abs
end

Better:

sorted_dates = dates.sort_by { |date| (date - test_date).abs }

Upvotes: 3

Related Questions