Ruby-哈希数组,重复项重复,将重复项重复的数组中的值保留

时间:2018-08-21 10:24:18

标签: arrays ruby hash duplicates

如何从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}所示)

2 个答案:

答案 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}]