将红宝石哈希值与相同的密钥合并



可以使用选定的键来实现:

例如

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"}

注意:这只是我要提出问题的哈希测试阵列。但是,实际哈希有很多钥匙。因此,请不要回复关键比较答案

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

我看不到您的代码的简单版本。为了使其充分工作,您可以在merge块中使用第一个参数,而不是当需要合并ab或仅使用a时将其解散以区分。您的行变为:

s.merge(l) { |key, a, b| key == :a ? a : [a, b].uniq.join(", ") }

也许您可以考虑此选项,但是我不知道它是否不那么复杂:

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"}]]

然后,它使用哈希#Merge

将第一元素与其他元素合并为合并
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"}] 

这使用了使用一个块(此处{ |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }(的哈希#更新的形式来确定两个正在合并的哈希中存在的密钥值。第一个块变量包含通用密钥。我使用该变量的下划线主要是向读者发出信号,即在块计算中不使用它。有关其他两个块变量的定义,请参见DOC。

请注意,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"} }

最新更新