如何在ruby中合并基于哈希的相同键的数组?
示例:
a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}]
如何得到这样的结果?
a = [{:a=>[1, 10]},{:b=>8},{:c=>[7, 2]}]
之前感谢
答案 0 :(得分:10)
尝试
a.flat_map(&:entries)
.group_by(&:first)
.map{|k,v| Hash[k, v.map(&:last)]}
答案 1 :(得分:5)
另一种选择:
a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}]
p a.each_with_object({}) { |h, o| h.each { |k,v| (o[k] ||= []) << v } }
# => {:a=>[1, 10], :b=>[8], :c=>[7, 2]}
当Hashes具有多个键/值组合时,它也有效,例如:
b = [{:a=>1, :b=>5, :x=>10},{:a=>10, :y=>2},{:b=>8},{:c=>7},{:c=>2}]
p b.each_with_object({}) { |h, o| h.each { |k,v| (o[k] ||= []) << v } }
# => {:a=>[1, 10], :b=>[5, 8], :x=>[10], :y=>[2], :c=>[7, 2]}
答案 2 :(得分:3)
Arie Shaw为回答所需答案而做出的回答:
a.flat_map(&:entries)
.group_by(&:first)
.map{|k,v| Hash[k, v.size.eql?(1) ? v.last.last : v.map(&:last) ]}
#=> [{:a=>[1, 10]}, {:b=>8}, {:c=>[7, 2]}]
答案 3 :(得分:1)
我会这样做:
a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}]
merged_hash = a.each_with_object({}) do |item,hsh|
k,v = item.shift
hsh[k] = hsh.has_key?(k) ? [ *Array( v ), hsh[k] ] : v
end
merged_hash.map { |k,v| { k => v } }
# => [{:a=>[10, 1]}, {:b=>8}, {:c=>[2, 7]}]
<强>更新强>
更好的口味:
a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}]
merged_hash = a.each_with_object({}) do |item,hsh|
k,v = item.shift
(hsh[k] ||= []) << v
end
merged_hash.map { |k,v| { k => v } }
# => [{:a=>[10, 1]}, {:b=>8}, {:c=>[2, 7]}]