如何从arr转到arr_result?
arr = [ {a => 1},
{a => 2},
{b => 3},
{b => 4},
{b => 10},
{c => 12},
{c => 16},
{d => 7} ]
arr_result = [ {a => [1,2] },
{b => [3,4,10] },
{c => [12,16] },
{d => 7 } ]
将键重复数据删除,并在发生dedup的数组中保留这些键的值。保留不发生重复数据删除的键/值(如示例中的{d => 7}所示)
答案 0 :(得分:2)
首先,您输入的内容不是有效的红宝石对象。
arr = [ {a: 1},
{a: 2},
{b: 3},
{b: 4},
{b: 10},
{c: 12},
{c: 16},
{d: 7} ]
arr.
map(&:flatten).
group_by(&:shift).
each { |_, v| v.flatten! }
#⇒ {:a=>[1, 2], :b=>[3, 4, 10], :c=>[12, 16], :d=>[7]}
确切地获得您想要的:
arr.
map(&:flatten).
group_by(&:shift).
map { |k, v| v.flatten! && { k => v.size == 1 ? v.first : v } }
#⇒ [{:a=>[1, 2]}, {:b=>[3, 4, 10]}, {:c=>[12, 16]}, {:d=>7}]
答案 1 :(得分:0)
您还可以将每个哈希表简化为一个新的哈希表,并按照以下步骤进行合并:
arr.reduce({}) do |memo,h|
memo.merge!(h) {|_,o,n| Array(o) << n}
end
#=> {:a=>[1, 2], :b=>[3, 4, 10], :c=>[12, 16], :d=>7}
然后,仅当添加第二个值时,才创建Array
值。
您的预期结果非常不常规,但是您可以通过将.map {|k,v| {k=> v}}
附加到上面的结果中来达到预期的结果:
arr.reduce({}) do |memo,h|
memo.merge!(h) {|_,o,n| Array(o) << n}
end.map {|k,v| {k=> v}}
#=> [{:a=>[1, 2]}, {:b=>[3, 4, 10]}, {:c=>[12, 16]}, {:d=>7}]
通常,您会希望@mudasobwa的原始方法返回什么,它是所有元素的key => Array
的单个哈希,这使得循环遍历变得容易得多。您也可以使用
arr.each_with_object(Hash.new {|h,k| h[k] = []}) do |h,obj|
h.each {|k,v| obj[k] << v}
end
#=> {:a=>[1, 2], :b=>[3, 4, 10], :c=>[12, 16], :d=>[7]}
获得当前期望结果的另一种方法:
arr.reduce([]) do |memo,h|
key,value = h.first
if r = memo.detect {|nh| nh.key?(key)}
r[key] = [*r[key],value]
else
memo << h
end
memo
end
#=> [{:a=>[1, 2]}, {:b=>[3, 4, 10]}, {:c=>[12, 16]}, {:d=>7}]