plin
plin

Reputation: 1

Ruby - complex sorting. Want part of the list to sort ascending, the other part to sort descending

I have multiple criteria for sorting

  1. I have a sort order that I specify. (I spit out 1, 2, 3, 4 base on the criteria I have)

  2. Then base on the order from step 1, I use different column for sorting.
  3. When step 1 produces 1 to 3, I need step 2 to sort ascending and when it is 4, I need it to be descending.

I have step 1 and 2 working. Stuck on step 3. The operation is also expensive, so I don't want to iterate the list more than once if I can avoid it.

I understand I could have first filter the list into 2 different arrays (such as group sort_order 1 to 3 into one array) and sort_order 4 into another array and then call reverse on the second array. But that would require me to iterate the list multiple times.

@assignments.sort_by do |a|
  sort_date = if(a.sort_order == 1 || a.sort_order == 4)
                a.due_date
              else
                a.start_date
              end
  [a.sort_order, sort_date]
end

example input -

[{name: item 1, start_date: "08/01/2016", due_date: "08/15/2016",  sort_order: 3}, 
 {name: item 2, start_date: "08/02/2016", due_date: "08/20/2016", sort_order: 3}, 
 {name: item 3, start_date: "06/01/2016", due_date: nil, sort_order: 2},
 {name: item 4, start_date: "06/01/2016", due_date: "07/15/2016", sort_order: 1},
 {name: item 5, start_date: "07/01/2016", due_date: "07/07/2016", sort_order: 1},
 {name: item 6, start_date: "01/01/2015", due_date: "01/15/2015", sort_order: 4},
 {name: item 7, start_date: "01/01/2016", due_date: "01/15/2016", sort_order: 4},]

the order of expected output

item 5
item 4
item 3
item 1
item 2
item 7
item 6

Basically sort the assignments by current, future, past.

  1. Current assignments could have no end date, therefore, they get sort order 1 and 2 and if the assignment is current, then sort it by due date unless there is no due date, then sort it by start date.
  2. Future assignments, sort it by start date ascending order.
  3. Past assignments, sort it by due date descending order.

Upvotes: 0

Views: 147

Answers (1)

SteveTurczyn
SteveTurczyn

Reputation: 36860

Just use negative values for the dates to sort descending.

@assignments.sort_by do |a|

  case a.sort_order
  when 1 then [1, a.due_date]
  when 2 then [2, a.start_date]
  when 3 then [3, a.start_date]
  when 4 then [4, -a.due_date]
  end
end

Upvotes: 2

Related Questions