我有这样的事情:
prods = [{"1050" => {"key" => "value", "key2" => "value2"}},
{"1050" => {"key" => "value", "key2" => "value2"}},
{"6650" => {"key" => "value", "key2" => "value2"}},
{"6650" => {"key" => "value", "key2" => "value2"}}]
我想合并重复项,但保留像这样的键值对
prods = [{"1050" => [{"key" => "value", "key2" => "value2"},
{"key" => "value", "key2" => "value2"}}],
{"6650" => [{"key" => "value", "key2" => "value2"},
{"key" => "value", "key2" => "value2"}}]
]
这可能吗?
答案 0 :(得分:1)
这是许多人可以做到的一种方式。
<强>代码强>
def combine(prods)
prods.map(&:flatten)
.each_with_object(Hash.new {|h,k| h[k]=[]}) { |(k,v),h| h[k] << v }
.map { |k,v| { k=>v } }
end
<强>实施例强>
您的prods
的价值:
combine(prods)
#=> [{"1050"=>[{"key"=>"value", "key2"=>"value2"},
# {"key"=>"value", "key2"=>"value2"}]},
# {"6650"=>[{"key"=>"value", "key2"=>"value2"},
# {"key"=>"value", "key2"=>"value2"}]}]
现在让我们重新定义prods:
prods = [{"1050" => {"keya" => "value1", "keyb" => "value1"}},
{"1050" => {"keya" => "value2", "keyb" => "value2"}},
{"6650" => {"keya" => "value3", "keyb" => "value3"}},
{"6650" => {"keya" => "value4", "keyb" => "value4"}}]
combine(prods)
#=> [{"1050"=>[{"keya"=>"value1", "keyb"=>"value1"},
# {"keya"=>"value2", "keyb"=>"value2"}]},
# {"6650"=>[{"keya"=>"value3", "keyb"=>"value3"},
# {"keya"=>"value4", "keyb"=>"value4"}]}]
<强>解释强>
以下是步骤:
a = prods.map(&:flatten)
#=> [["1050", {"key"=>"value", "key2"=>"value2"}],
# ["1050", {"key"=>"value", "key2"=>"value2"}],
# ["6650", {"key"=>"value", "key2"=>"value2"}],
# ["6650", {"key"=>"value", "key2"=>"value2"}]]
h = a.each_with_object(Hash.new {|h,k| h[k]=[]}) { |(k,v),h| h[k] << v }
#=> {"1050"=>[{"key"=>"value", "key2"=>"value2"},
# {"key"=>"value", "key2"=>"value2"}],
# "6650"=>[{"key"=>"value", "key2"=>"value2"},
# {"key"=>"value", "key2"=>"value2"}]}
最后,
h.map { |k,v| { k=>v } }
产生上面显示的结果。
在计算h
Enumerable#each_with_object中,对象是块变量h
的值。最初,h
是一个空哈希,定义如下:
Hash.new {|h,k| h[k]=[]}
该块给出了哈希的默认值。这表示如果h
是散列并且k
是要添加到散列的键,则它的默认值是空数组。传递给a
块的each_with_object
的第一个值是:
["1050", {"key"=>"value", "key2"=>"value2"}]
因此,块变量分配如下:
(k,v),h = [["1050", {"key"=>"value", "key2"=>"value2"}], {}]
#=> [["1050", {"key"=>"value", "key2"=>"value2"}], {}]
k #=> "1050"
v #=> {"key"=>"value", "key2"=>"value2"}
h #=> {}
并且块计算是:
h[k] << v
是:
h["1050"] << {"key"=>"value", "key2"=>"value2"}
由于h
没有密钥"1050"
,h["1050"]
首先被分配了默认值,即空哈希,所以我们有:
(h["1050"] = []) << {"key"=>"value", "key2"=>"value2"}
哈希h
现在是:
h #=> { "1050"=>[{"key"=>"value", "key2"=>"value2"}] }
a
的下一个值传递给块,导致块变量更新如下:
(k,v),h = [["1050", {"key"=>"value", "key2"=>"value2"}],
{ "1050"=>[{"key"=>"value", "key2"=>"value2"}] }]
k #=> "1050"
v #=> {"key"=>"value", "key2"=>"value2"}
h #=> {"1050"=>[{"key"=>"value", "key2"=>"value2"}]}
因此,块计算是:
h[k] << v
# h["1050"] << {"key"=>"value", "key2"=>"value2"}
由于h
现在具有键"1050"
(其值为数组),因此不使用默认值,并且哈希h
变为
h #=> {"1050"=>[{"key"=>"value", "key2"=>"value2"},
# {"key"=>"value", "key2"=>"value2"}]}
其余的计算也是类似的。
答案 1 :(得分:0)
h = Hash.new {[]} # this creates a new array when a key doesn't exist
prods.each do |prod|
prod.each{ |key,val| h[key] = h[key] << val }
end
puts h
答案 2 :(得分:0)
以下是我提出的解决方案:
results =
prods.each_with_object(Hash.new([])) do |hash, results|
key = hash.keys.first
values = hash.values
results[key] += values
end
results = results.map { |k, v| Hash[k, v] }
在这个解决方案中,我只使用带有默认值的哈希来处理重复项,然后转换为所需的输出格式。
替代解决方案:
def find_hash(haystack, needle)
haystack.index { |hay| hay.keys.first == needle }
end
results =
prods.each_with_object(Array.new) do |hash, results|
key = hash.keys.first
values = hash.values
idx = find_hash(results, key)
if idx
results[idx][key] += values
else
results << Hash[key, values]
end
end
在这里,我尝试查找是否已存在具有指定键的哈希,然后附加到它,否则创建一个新哈希并将其添加到数组中。