Ruby从哈希数组中选择最近重复的值



假设我有这样一个数组

a = [
{key: "cat", value: 1},
{key: "dog", value: 2},
{key: "mouse", value: 5},
{key: "rat", value: 3},
{key: "cat", value: 5},
{key: "rat", value: 2},
{key: "cat", value: 1},
{key: "cat", value: 1}
]

假设我有这个数组,并且只想获取"cat"的最新值。

我知道如何选择所有的

a.select do |e|
e[:key] == "cat"
end

但是我正在寻找一种方法来获取最后3个

的选择期望的结果是

[
{key: "cat", value: 5},
{key: "cat", value: 1},
{key: "cat", value: 1}
]

谢谢!

在@Stefan提出的问题的评论中:

a.select { |e| e[:key] == "cat" }.last(3)

如果a不是太大,您可能应该使用它。然而,如果a很大,特别是如果它包含许多元素(哈希值)h对应h[:key] #=> "cat",那么从数组的末尾向后迭代并在找到h[:key] #=> "cat"对应的三个元素h时终止("短路")可能会更有效。这也避免了构造一个可能很大的临时数组(a.select { |e| e[:key] == "cat" })。


方法如下:

a.reverse_each.with_object([]) do |h,arr|
arr.insert(0,h) if h[:key] == "cat"
break arr if arr.size == 3
end
#=> [{:key=>"cat", :value=>5},
#    {:key=>"cat", :value=>1},
#    {:key=>"cat", :value=>1}]

参见array# reverse_each, Enumerator#with_object和array# insert。注意,由于reverse_eachwith_object都返回枚举数,因此将它们链接起来也会生成一个枚举数:

a.reverse_each.with_object([])
#=> #<Enumerator: #<Enumerator: [{:key=>"cat", :value=>1},
#   ...
#   {:key=>"cat", :value=>1}]:reverse_each>:with_object([])>

代替块计算可能会稍微快一点
arr << h if h[:key] == "cat"
break arr.reverse if arr.size == 3

如果a包含较少的元素h,而h[:key] #=> "cat"将返回一个数组arr,而arr.size < 3。因此有必要确认返回的数组包含三个元素。

当使用@Stefan建议的代码时,也必须执行此检查,例如

a.select { |e| e[:key] == "cat" }.last(99)
#=> [{:key=>"cat", :value=>1},
#    {:key=>"cat", :value=>5},
#    {:key=>"cat", :value=>1},
#    {:key=>"cat", :value=>1}]

相关内容

  • 没有找到相关文章

最新更新