data = [{'id' => 1, 'num' => 10},
{'id' => 1, 'num' => 5},
{'id' => 1, 'num' => 8},
{'id' => 2, 'num' => 0},
{'id' => 2, 'num' => 20},
{'id' => 2, 'num' => -5},
{'id' => 5, 'num' => 9},
{'id' => 5, 'num' => 9}]
I want to order this information by groups of the same id
according to the max num
associated with each group of id
. Then within each group, the num
can also be used for further ordering.
data_transformed =
[{'id' => 2, 'num' => 20},
{'id' => 2, 'num' => 0},
{'id' => 2, 'num' => -5},
{'id' => 1, 'num' => 10},
{'id' => 1, 'num' => 8},
{'id' => 1, 'num' => 5},
{'id' => 5, 'num' => 9},
{'id' => 5, 'num' => 9}]
This would also be fine
data_transformed =
[[{'id' => 2, 'num' => 20},
{'id' => 2, 'num' => 0},
{'id' => 2, 'num' => -5}],
[{'id' => 1, 'num' => 10},
{'id' => 1, 'num' => 8},
{'id' => 1, 'num' => 5}],
[{'id' => 5, 'num' => 9},
{'id' => 5, 'num' => 9}]]
How can I do this?
I'd do :
data = [{'id' => 1, 'num' => 10},
{'id' => 1, 'num' => 5},
{'id' => 1, 'num' => 8},
{'id' => 2, 'num' => 0},
{'id' => 2, 'num' => 20},
{'id' => 2, 'num' => -5},
{'id' => 5, 'num' => 9},
{'id' => 5, 'num' => 9}]
data_grouped_ordered_by_num = data.group_by { |h| h['id'] }.sort_by { |_,v| v.map { |h| h['num'] }.max }.reverse
# => [[2, [{"id"=>2, "num"=>0}, {"id"=>2, "num"=>20}, {"id"=>2, "num"=>-5}]],
# [1, [{"id"=>1, "num"=>10}, {"id"=>1, "num"=>5}, {"id"=>1, "num"=>8}]],
# [5, [{"id"=>5, "num"=>9}, {"id"=>5, "num"=>9}]]]
data_grouped_ordered_by_num.map { |k,v| v.sort_by {|h| -h['num']} }
# => [[{"id"=>2, "num"=>20}, {"id"=>2, "num"=>0}, {"id"=>2, "num"=>-5}],
# [{"id"=>1, "num"=>10}, {"id"=>1, "num"=>8}, {"id"=>1, "num"=>5}],
# [{"id"=>5, "num"=>9}, {"id"=>5, "num"=>9}]]
data.group_by{ |x| x['id'] }.values.map do |x|
x.sort_by do |y|
-y['num']
end
end
#=> [[{"id"=>1, "num"=>10}, {"id"=>1, "num"=>8}, {"id"=>1, "num"=>5}],
[{"id"=>2, "num"=>20}, {"id"=>2, "num"=>0}, {"id"=>2, "num"=>-5}],
[{"id"=>5, "num"=>9}, {"id"=>5, "num"=>9}]]
You can use flatten
after that to flat the result which will give you your first desired output:
[{"id"=>1, "num"=>10},
{"id"=>1, "num"=>8},
{"id"=>1, "num"=>5},
{"id"=>2, "num"=>20},
{"id"=>2, "num"=>0},
{"id"=>2, "num"=>-5},
{"id"=>5, "num"=>9},
{"id"=>5, "num"=>9}]
data.sort_by { |h| [h['id'], -h['num']] }
#=> [{'id' => 1, 'num'=>10}, {'id'=>1, 'num'=>8}, {'id'=>1, 'num'=> 5},
# {'id' => 2, 'num'=>20}, {'id'=>2, 'num'=>0}, {'id'=>2, 'num'=>-5},
# {'id' => 5, 'num'=> 9}, {'id'=>5, 'num'=>9}]
For the second format:
data.sort_by { |h| [h['id'], -h['num']] }.chunk { |h| h['id'] }.map(&:last)
#=> [[{"id"=>1, "num"=>10}, {"id"=>1, "num"=>8}, {"id"=>1, "num"=> 5}],
# [{"id"=>2, "num"=>20}, {"id"=>2, "num"=>0}, {"id"=>2, "num"=>-5}],
# [{"id"=>5, "num"=> 9}, {"id"=>5, "num"=>9}]]
Array#sort_by uses Array#<=> for comparisons. Documentation for the latter explains why this produces the desired result.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.