用相同的键合并Ruby Hash值

时间:2019-05-15 16:21:45

标签: ruby

是否可以通过选择按键来实现:

例如

h = [
  {a: 1, b: "Hello", c: "Test1"},
  {a: 2, b: "Hey", c: "Test1"},
  {a: 3, b: "Hi", c: "Test2"}
]

预期产量

[
  {a: 1, b: "Hello, Hey", c: "Test1"}, # See here, I don't want key 'a' to be merged
  {a: 3, b: "Hi", c: "Test2"}
]

我的尝试

g = h.group_by{|k| k[:c]}.values
OUTPUT =>
  [
    [
      {:a=>1, :b=>"Hello", :c=>"Test1"},
      {:a=>2, :b=>"Hey", :c=>"Test1"}
    ], [
      {:a=>3, :b=>"Hi", :c=>"Test2"}
    ]
  ]

g.each do |v|
  if v.length > 1
    c = v.reduce({}) do |s, l|
      s.merge(l) { |_, a, b| [a, b].uniq.join(", ") }
    end
  end

  p c #{:a=>"1, 2", :b=>"Hello, Hey", :c=>"Test1"}
end

所以,我得到的输出是

{:a=>"1, 2", :b=>"Hello, Hey", :c=>"Test1"}

但是,我需要

{a: 1, b: "Hello, Hey", c: "Test1"}

注意::这只是我提出问题的HASH测试数组。但是,实际的哈希值有很多键。因此,请不要给出关键的比较答案

我需要一个不太复杂的解决方案

3 个答案:

答案 0 :(得分:3)

我看不到您的代码的简单版本。要使其完全正常工作,您可以使用merge块中的第一个参数,而不必在需要合并ab或仅使用{{1 }}。您的行将变为:

a

答案 1 :(得分:1)

也许您可以考虑使用此选项,但是我不知道它是否那么简单:

h.group_by { |h| h[:c] }.values.map { |tmp| tmp[0].merge(*tmp[1..]) { |key, oldval, newval| key == :b ? [oldval, newval].join(' ') : oldval } }
#=> [{:a=>1, :b=>"Hello Hey", :c=>"Test1"}, {:a=>3, :b=>"Hi", :c=>"Test2"}]

第一部分按:c

对哈希进行分组
h.group_by { |h| h[:c] }.values #=> [[{:a=>1, :b=>"Hello", :c=>"Test1"}, {:a=>2, :b=>"Hey", :c=>"Test1"}], [{:a=>3, :b=>"Hi", :c=>"Test2"}]]

然后它映射为使用Hash#merge

将第一个元素与其他元素合并

答案 2 :(得分:1)

h.each_with_object({}) do |g,h|
  h.update(g[:c]=>g) { |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }
end.values
  #=> [{:a=>1, :b=>"Hello, Hey", :c=>"Test1"},
  #    {:a=>3, :b=>"Hi", :c=>"Test2"}] 

这使用Hash#update的形式,该形式采用一个块(此处为{ |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") })来确定两个合并的散列中存在的键的值。第一个块变量保存公用密钥。我对该变量使用了下划线,主要是为了向读者表明该变量未在块计算中使用。有关其他两个块变量的定义,请参阅文档。

请注意,values的接收者等于。

h.each_with_object({}) do |g,h|
  h.update(g[:c]=>g) { |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }
end
  #=> { “Test1”=>{:a=>1, :b=>"Hello, Hey", :c=>"Test1"},
  #     “Test2=>{:a=>3, :b=>"Hi", :c=>"Test2"} }