假设我有一系列像这样的哈希:
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 }
]
答案 0 :(得分:4)
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(aka merge!
)的形式,它使用一个块来确定合并的两个哈希中存在的键的值。请参阅文档以获取对三个块变量的解释(第一个是公共密钥,我用下划线表示它代表它未在块计算中使用)。
答案 1 :(得分:1)
如果您的数据非常简单,那么您可以按照自己的意愿行事:
{ foo: "dup",
bars: arr_with_dup_hsh_keys.map {|hsh| hsh[:bar] }
}
答案 2 :(得分:1)
这就是我的想法:
a = [
{ foo: "dup", bar: 1 },
{ foo: "dup", bar: 2 },
{ foo: "dup", bar: 3 },
{ foo: "dup", bar: 4 },
{ foo: "dup", bar: 5 }
]
h = {}
a.map(&:keys).uniq.flatten.each_with_index do |key, idx|
h[key] = a.map(&:values).collect { |a| a[idx]}.uniq
end
h
#=> {:foo=>["dup"], :bar=>[1, 2, 3, 4, 5]}