Reputation: 7314
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
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
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
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