raphael_turtle
raphael_turtle

Reputation: 7314

Sort array of arrays by array value into hash in ruby

I have an array of arrays

[ [1,23,true], [2,33,false],[3,44,true] ]

I'm trying to sort the array based on the [2] value of each inner array, so the outcome would be

true_values: [ [1,23,true],[3,44,true] ]
false_values: [ [2,33,false] ]

I can select the array objects but am looking for a succinct way of sorting and outputting a hash.

Upvotes: 1

Views: 769

Answers (3)

hirolau
hirolau

Reputation: 13901

x = [ [1,23,true], [2,33,false],[3,44,true] ]

Since group_by keeps the order you can sort before you group by:

p x.sort_by{|x|x[1]}.group_by(&:last) #=> {true=>[[1, 23, true], [3, 44, true]], false=>[[2, 33, false]]}

and if you do not need to keep the true/false value in the hash:

p  x.sort_by{|x|x[1]}.group_by(&:pop) #=> {true=>[[1, 23], [3, 44]], false=>[[2, 33]]}

Upvotes: 4

Cary Swoveland
Cary Swoveland

Reputation: 110675

Here's one way:

arr = [[1, 44, true], [2, 33, false], [3, 23, true]]

arr.sort_by { |*_,tf| (tf && 0) || 1 }.chunk { |*_,tf| tf }.to_h
  #=> {true=>[[1, 44, true], [3, 23, true]], false=>[[2, 33, false]]}     

If you want ties broken by, say, arr[i][1], then:

arr.sort_by { |_,e,tf| [(tf && 0) || 1, e] }.chunk { |*_,tf| tf }.to_h
  #=> {true=>[[3, 23, true], [1, 44, true]], false=>[[2, 33, false]]}

Notice that I've changed arr given in the question to make the second point.

Upvotes: 1

Anthony
Anthony

Reputation: 15957

Here I'm using Enumerable#group_by to group it by it true or false first, then sorting that hash by the contents of the second element of the array found in v. Lastly we call .to_h or to hash to get the format you outlined above.

[10] pry(main)> arr
=> [[1, 23, true], [2, 33, false], [3, 44, true]]
[11] pry(main)> arr.group_by { |x| x[2] }.sort_by { |_, v| v.map { |i| i[1] } }.to_h
=> {true=>[[1, 23, true], [3, 44, true]], false=>[[2, 33, false]]}

Upvotes: 1

Related Questions