我在ruby中有一系列哈希:
[
{name: 'one', tags: 'xxx'},
{name: 'two', tags: 'yyy'},
{name: 'one', tags: 'zzz'},
]
我正在寻找任何干净的红宝石解决方案,这将使它能够简单地合并该数组中的所有重复项(通过合并我的意思是合并tags
参数),所以上面的例子将转换为:
[
{name: 'one', tags: 'xxx, zzz'},
{name: 'two', tags: 'yyy'},
]
我可以迭代每个数组元素,检查是否有重复,将其与原始条目合并并删除副本但我觉得可以有更好的解决方案,并且这种方法有一些警告我不知道。谢谢你的任何线索。
答案 0 :(得分:6)
我可以认为是
arr = [
{name: 'one', tags: 'xxx'},
{name: 'two', tags: 'yyy'},
{name: 'one', tags: 'zzz'},
]
merged_array_hash = arr.group_by { |h1| h1[:name] }.map do |k,v|
{ :name => k, :tags => v.map { |h2| h2[:tags] }.join(" ,") }
end
merged_array_hash
# => [{:name=>"one", :tags=>"xxx ,zzz"}, {:name=>"two", :tags=>"yyy"}]
答案 1 :(得分:3)
这是一种利用Hash#update(又名Hash.merge!
)形式的方法,它采用一个块来确定两个哈希值中存在的每个键的合并值被合并。
<强>代码强>
def combine(a)
a.each_with_object({}) { |g,h| h.update({ g[:name]=>g }) { |k,hv,gv|
{ name: k, tags: hv[:tags]+", "+gv[:tags] } } }.values
end
示例强>
a = [{name: 'one', tags: 'uuu'},
{name: 'two', tags: 'vvv'},
{name: 'one', tags: 'www'},
{name: 'six', tags: 'xxx'},
{name: 'one', tags: 'yyy'},
{name: 'two', tags: 'zzz'}]
combine(a)
#=> [{:name=>"one", :tags=>"uuu, www, yyy"},
# {:name=>"two", :tags=>"vvv, zzz" },
# {:name=>"six", :tags=>"xxx" }]
<强>解释强>
假设
a = [{name: 'one', tags: 'uuu'},
{name: 'two', tags: 'vvv'},
{name: 'one', tags: 'www'}]
b = a.each_with_object({})
#=> #<Enumerator: [{:name=>"one", :tags=>"uuu"},
# {:name=>"two", :tags=>"vvv"},
# {:name=>"one", :tags=>"www"}]:each_with_object({})>
我们可以将枚举器b
转换为数组,以查看它将传递到其块中的值:
b.to_a
#=> [[{:name=>"one", :tags=>"uuu"}, {}],
# [{:name=>"two", :tags=>"vvv"}, {}],
# [{:name=>"one", :tags=>"www"}, {}]]
传递给块并分配给块变量的第一个值是:
g,h = [{:name=>"one", :tags=>"uuu"}, {}]
g #=> {:name=>"one", :tags=>"uuu"}
h #=> {}
现在执行第一个合并操作(返回合并的h
):
h.update({ g[:name] => g })
#=> h.update({ "one" => {:name=>"one", :tags=>"uuu"} })
#=> {"one"=>{:name=>"one", :tags=>"uuu"}}
h
没有密钥"one"
,因此update
&#39}的区块不会被调用。
接下来,枚举器b
将以下内容传递给块:
g #=> {:name=>"two", :tags=>"vvv"}
h #=> {"one"=>{:name=>"one", :tags=>"uuu"}}
所以我们执行:
h.update({ g[:name] => g })
#=> h.update({ "two"=>{:name=>"two", :tags=>"vvv"})
#=> {"one"=>{:name=>"one", :tags=>"uuu"},
# "two"=>{:name=>"two", :tags=>"vvv"}}
同样,h
没有密钥"two"
,因此不使用该块。
最后,each_with_object
将最后一个元组传递到块中:
g #=> {:name=>"one", :tags=>"www"}
h #=> {"one"=>{:name=>"one", :tags=>"uuu"},
# "two"=>{:name=>"two", :tags=>"vvv"}}
我们执行:
h.update({ g[:name] => g })
#=> h.update({ "one"=>{:name=>"one", :tags=>"www"})
h
具有键"one"
的键/值对:
"one"=>{:name=>"one", :tags=>"uuu"}
因此,执行 update
块以确定合并值。以下值将传递给该块的变量:
k #=> "one"
hv #=> {:name=>"one", :tags=>"uuu"} <h's value for "one">
gv #=> {:name=>"one", :tags=>"www"} <g's value for "one">
并且块计算创建此哈希值(作为键的合并值&#34;一个&#34;):
{ name: k, tags: hv[:tags]+", "+gv[:tags] }
#=> { name: "one", tags: "uuu" + ", " + "www" }
#=> { name: "one", tags: "uuu, www" }
所以现在合并的哈希变为:
h #=> {"one"=>{:name=>"one", :tags=>"uuu, www"},
# "two"=>{:name=>"two", :tags=>"vvv" }}
剩下的就是提取值:
h.values
#=> [{:name=>"one", :tags=>"uuu, www"}, {:name=>"two", :tags=>"vvv"}]