Reputation: 10551
How can I sort the following array's hashes by their :type ? I want to sort them numerically, in a cyclical fashion. What I mean by that is have the types go 0,1,0,1,0,1
Current array:
values = [{value: "First", type: 0},{value: "Second", type: 0},{value: "1111", type: 1},{value: "2222", type: 1}]
How it needs to look:
values = [{value: "First", type: 0},{value: "1111", type: 1},{value: "Second", type: 0},{value: "2222", type: 1}]
I can sort it numerically like this:
values.sort_by! { |x| x[:type] }
I bring all the items with a type equal to 1 to the start of the array like this:
values.sort_by! { |x| x[:type] == 1 ? 1 : 0}
But I can't manipulate the array as intricately as I need to. Honestly, been googling for hours. I know how to order things numerically and alphabetically and everything under the sun, but I can't get in there and say exactly what I want to happen.
Maybe if I could iterate a variable to track how many times the block has been used, I could use an if statement, so when iterator == 2 (meaning it's ordered one set of 0 and 1) it could order the next pair, but there's literally nothing I can find. Is the sort_by method the right method for this?
I'd like it to be dynamic as well. If the array looks like this:
values = [{value: "First", type: 0},{value: "Second", type: 0},{value: "1111", type: 1},{value: "2222", type: 1},{value: "Un", type: 2},{value: "Deux", type: 2}]
It should then look like this:
values = [{value: "First", type: 0},{value: "1111", type: 1},{value: "Un", type: 2},{value: "Second", type: 0},{value: "2222", type: 1},{value: "Deux", type: 2}]
Disappointed that I can't work this out, but I just don't know enough about sorting arrays with custom methods. Only using the ruby defaults of ascending and descending.
The number of 'types' will always be consistent. The order of the :types (before ordering it) will always look like this:
0,0,0,1,1,1
or
0,0,0,1,1,1,2,2,2
no 0,1,1,2 or anything.
Simpler example:
[0,0,1,1,2,2] needs to be sorted as [0,1,2,0,1,2]
The sorting method needs to be dynamic, so it can do this as well:
[0,0,1,1,2,2,3,3] needs to be sorted as [0,1,2,3,0,1,2,3]
Upvotes: 1
Views: 80
Reputation: 10551
For the benefit of future visitors, don't get confused by SHiNKiROU's use of the '.values' method. It isn't referencing the 'values' array somehow. (It's my fault, I shouldn't have called the array 'values'.)
Just to make it clear:
foobar = [{value: "First", type: 0},{value: "Second", type: 0},{value: "1111", type: 1},{value: "2222", type: 1},{value: "un", type: 2},{value: "deux", type: 2}]
groups = foobar.group_by { |v| v[:type] }
puts groups.values.transpose.flatten
Not doing this for any cruddy rep, just trying to help others.
Upvotes: 4
Reputation: 17651
groups = values.group_by { |v| v[:type] }
puts groups.values.transpose.flatten
Upvotes: 3
Reputation: 6076
use zip:
values1 = values.select {|h| h[:type] == 0 }
values2 = values.select {|h| h[:type] == 1 }
values1.zip(values2).flatten
=> [{:value=>"First", :type=>0}, {:value=>"1111", :type=>1}, {:value=>"Second", :type=>0}, {:value=>"2222", :type=>1}]
Upvotes: 1