如何合并两个哈希数组
How to merge two arrays of hashes
我有两个哈希数组:
a = [
{
key: 1,
value: "foo"
},
{
key: 2,
value: "baz"
}
]
b = [
{
key: 1,
value: "bar"
},
{
key: 1000,
value: "something"
}
]
我想将它们合并到一个哈希数组中,所以本质上是 a + b
除了我希望 b
中的任何重复键覆盖 a
中的键。在这种情况下,a
和 b
都包含一个键 1
,我希望最终结果具有 b
的键值对。
这是预期的结果:
expected = [
{
key: 1,
value: "bar"
},
{
key: 2,
value: "baz"
},
{
key: 1000,
value: "something"
}
]
我让它工作了,但我想知道是否有更简洁的方法来做到这一点:
hash_result = {}
a.each do |item|
hash_result[item[:key]] = item[:value]
end
b.each do |item|
hash_result[item[:key]] = item[:value]
end
result = []
hash_result.each do |k,v|
result << {:key => k, :value => v}
end
puts result
puts expected == result # prints true
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
.reduce(&:merge)
.flat_map(&:last)
这里我们使用 hash[:key]
作为构建新哈希的键,然后我们 merge
他们用最后一个值覆盖所有内容 return values
.
如果以相反的顺序连接数组,uniq
会起作用:
(b + a).uniq { |h| h[:key] }
#=> [
# {:key=>1, :value=>"bar"},
# {:key=>1000, :value=>"something"},
# {:key=>2, :value=>"baz"}
# ]
但是它不保留顺序。
我会稍微重建你的数据,因为散列中有冗余键:
thin_b = b.map { |h| [h[:key], h[:value]] }.to_h
#=> {1=>"bar", 1000=>"something"}
thin_a = b.map { |h| [h[:key], h[:value]] }.to_h
#=> {1=>"bar", 1000=>"something"}
那么你可以只使用 Hash#merge
:
thin_a.merge(thin_b)
#=> {1=>"bar", 2=>"baz", 1000=>"something"}
但是,如果你愿意,你可以获得问题中提到的准确结果:
result.map { |k, v| { key: k, value: v } }
#=> [{:key=>1, :value=>"bar"},
# {:key=>2, :value=>"baz"},
# {:key=>1000, :value=>"something"}]
使用Enumerable#group_by and Enumerable#map
(b+a).group_by { |e| e[:key] }.values.map {|arr| arr.first}
如果您需要合并两个也应该合并的哈希数组,并且有两个以上的键,那么下一个片段应该会有所帮助:
[a, b].flatten
.compact
.group_by { |v| v[:key] }
.values
.map { |e| e.reduce(&:merge) }
我有两个哈希数组:
a = [
{
key: 1,
value: "foo"
},
{
key: 2,
value: "baz"
}
]
b = [
{
key: 1,
value: "bar"
},
{
key: 1000,
value: "something"
}
]
我想将它们合并到一个哈希数组中,所以本质上是 a + b
除了我希望 b
中的任何重复键覆盖 a
中的键。在这种情况下,a
和 b
都包含一个键 1
,我希望最终结果具有 b
的键值对。
这是预期的结果:
expected = [
{
key: 1,
value: "bar"
},
{
key: 2,
value: "baz"
},
{
key: 1000,
value: "something"
}
]
我让它工作了,但我想知道是否有更简洁的方法来做到这一点:
hash_result = {}
a.each do |item|
hash_result[item[:key]] = item[:value]
end
b.each do |item|
hash_result[item[:key]] = item[:value]
end
result = []
hash_result.each do |k,v|
result << {:key => k, :value => v}
end
puts result
puts expected == result # prints true
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
.reduce(&:merge)
.flat_map(&:last)
这里我们使用 hash[:key]
作为构建新哈希的键,然后我们 merge
他们用最后一个值覆盖所有内容 return values
.
uniq
会起作用:
(b + a).uniq { |h| h[:key] }
#=> [
# {:key=>1, :value=>"bar"},
# {:key=>1000, :value=>"something"},
# {:key=>2, :value=>"baz"}
# ]
但是它不保留顺序。
我会稍微重建你的数据,因为散列中有冗余键:
thin_b = b.map { |h| [h[:key], h[:value]] }.to_h
#=> {1=>"bar", 1000=>"something"}
thin_a = b.map { |h| [h[:key], h[:value]] }.to_h
#=> {1=>"bar", 1000=>"something"}
那么你可以只使用 Hash#merge
:
thin_a.merge(thin_b)
#=> {1=>"bar", 2=>"baz", 1000=>"something"}
但是,如果你愿意,你可以获得问题中提到的准确结果:
result.map { |k, v| { key: k, value: v } }
#=> [{:key=>1, :value=>"bar"},
# {:key=>2, :value=>"baz"},
# {:key=>1000, :value=>"something"}]
使用Enumerable#group_by and Enumerable#map
(b+a).group_by { |e| e[:key] }.values.map {|arr| arr.first}
如果您需要合并两个也应该合并的哈希数组,并且有两个以上的键,那么下一个片段应该会有所帮助:
[a, b].flatten
.compact
.group_by { |v| v[:key] }
.values
.map { |e| e.reduce(&:merge) }