可以使用选定的键来实现:
例如
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
块中使用第一个参数,而不是当需要合并a
和b
或仅使用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"} }