嘿,我有一个数组,其中每个元素都是一个包含几个值和一个数的哈希。
result = [
{"count" => 3,"name" => "user1"},
{"count" => 10,"name" => "user2"},
{"count" => 10, "user3"},
{"count" => 2, "user4"}
]
我可以按如下方式对数组进行排序:
result = result.sort_by do |r|
r["count"]
end
现在我希望能够根据计数检索前n个条目(不仅仅是第一个(n))是否有一种优雅的方式来执行此操作? 举个例子,假设n = 1,我希望得到一个结果集。
[{"count" => 10,"name" => "user2"}, {"count" => 10, "user3"}]
因为我要求得分最高的所有参赛作品..如果我要求获得前2名最高分,我会得到
[{"count" => 10,"name" => "user2"}, {"count" => 10, "user3"}, {"count" => 3, "user1"}]
答案 0 :(得分:24)
Enumerable#group_by
救援(像往常一样):
result.group_by { |r| r["count"] }
.sort_by { |k, v| -k }
.first(2)
.map(&:last)
.flatten
大部分工作都是由group_by
完成的。 sort_by
只是简单地排列,以便first(2)
能够挑选出您想要的群组。然后使用map
last
将提取您开始使用的计数/名称哈希值,最终flatten
将清除数组上的额外左侧。
答案 1 :(得分:2)
这种解决方案在简洁方面并不优雅,但它具有更好的时间复杂性。 换句话说,对于大量哈希值,它应该执行得更快。
您需要安装"algorithms" gem才能使用堆数据结构:
当您需要查找组中的最大或最小元素时,Heaps是一种高效的数据结构。如果“n”的值远小于对的总数,则此特定类型的堆为optimal。
require 'algorithms'
def take_highest(result,n)
max_heap = Containers::Heap.new(result){|x,y| (x["count"] <=> y["count"]) == 1}
last = max_heap.pop
count = 0
highest = [last]
loop do
top = max_heap.pop
break if top.nil?
count += (top["count"] == last["count"] ? 0 : 1)
break if count == n
highest << top
last = top
end
highest
end
答案 2 :(得分:2)
new_result = result.
sort_by { |r| -r["count"] }.
chunk { |r| r["count"] }.
take(2).
flat_map(&:last)
#=> [{"count"=>10, "name"=>"user3"},
# {"count"=>10, "name"=>"user2"},
# {"count"=> 3 "name"=>"user1"}]
答案 3 :(得分:2)
从Ruby 2.2.0开始,max_by
需要一个额外的参数,让你可以要求一定数量的顶级元素而不是只获得一个。使用这个,我们可以改进 mu太短的答案
result = [
{count: 3, name: 'user1'},
{count: 10, name: 'user2'},
{count: 10, name: 'user3'},
{count: 2, name: 'user4'}
]
p result.group_by { |r| r[:count] }
.max_by(2, &:first)
.flat_map(&:last)
.sort_by { |r| -r[:count] }
# => [{:count=>10, :name=>"user2"}, {:count=>10, :name=>"user3"}, {:count=>3, :name=>"user1"}]
文档不会说明max_by
返回的数组是否已排序。如果结果证明是真的,我们可以在最后一步使用reverse
而不是排序。