Note: There were a few similar questions on SO about this, like here and here, but none seem quite like what I'm looking for.
假设我有一个这样的哈希数组:
arr_with_dup_hsh_keys = [
{ foo: "dup", bar: 1 },
{ foo: "dup", bar: 2 },
{ foo: "dup", bar: 3 },
{ foo: "dup", bar: 4 },
{ foo: "dup", bar: 5 }
]
我如何将其减少到这个?
{ foo: "dup", bars: [1, 2, 3, 4, 5] }
如果 foo
有不同的值怎么办?
arr_with_dup_hsh_keys = [
{ foo: "dup", bar: 1 },
{ foo: "dup", bar: 2 },
{ foo: "soup", bar: 3 },
{ foo: "dup", bar: 4 },
{ foo: "soup", bar: 5 }
]
最佳答案
def combine(arr)
arr.group_by {|g|g[:foo]}.map {|_,a|{foo: a.first[:foo], bar: a.map {|g| g[:bar]}}}
end
combine arr_with_dup_hsh_keys
#=> [{:foo=>"dup", :bar=>[1, 2, 3, 4, 5]}]
arr_with_dup_hsh_keys1 = [
{ foo: "dup", bar: 1 },
{ foo: "dup", bar: 2 },
{ foo: "soup", bar: 3 },
{ foo: "dup", bar: 4 },
{ foo: "soup", bar: 5 }
]
combine arr_with_dup_hsh_keys1
#=> [{:foo=>"dup", :bar=>[1, 2, 4]}, {:foo=>"soup", :bar=>[3, 5]}]
参见 Enumerable#group_by并注意
arr_with_dup_hsh_keys1.group_by { |g| g[:foo] }
#=> {"dup"=> [{:foo=>"dup", :bar=>1}, {:foo=>"dup", :bar=>2},
# {:foo=>"dup", :bar=>4}],
# "soup"=>[{:foo=>"soup", :bar=>3}, {:foo=>"soup", :bar=>5}]}
您也可以编写以下内容。
def combine(arr)
arr.each_with_object({}) do |g,h|
f = g.merge(bar: [g[:bar]])
h.update(f[:foo]=>f) { |_,o,n| { foo: o[:foo], bar: o[:bar]+n[:bar] } }
end.values
end
combine arr_with_dup_hsh_keys1
#=> [{:foo=>"dup", :bar=>[1, 2, 4]}, {:foo=>"soup", :bar=>[3, 5]}]
这使用了 Hash#update 的形式(又名 merge!
),它使用一个 block 来确定要合并的两个散列中存在的键的值。有关三个 block 变量的解释,请参阅文档(第一个是公共(public)键,我用下划线表示它表示它不用于 block 计算)。
关于arrays - 如何将具有重复键的散列数组 "reduce"嵌套散列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39398382/