I have two arrays of hashes:
我有两个哈希数组:
a = [
{
key: 1,
value: "foo"
},
{
key: 2,
value: "baz"
}
]
b = [
{
key: 1,
value: "bar"
},
{
key: 1000,
value: "something"
}
]
I want to merge them into one array of hashes, so essentially a + b
except I want any duplicated key in b
to overwrite those in a
. In this case, both a
and b
contain a key 1
and I want the final result to have b
's key value pair.
我想将它们合并为一个哈希数组,所以基本上是一个+ b,除了我想要b中的任何重复键来覆盖a中的那些。在这种情况下,a和b都包含键1,我希望最终结果具有b的键值对。
Here's the expected result:
这是预期的结果:
expected = [
{
key: 1,
value: "bar"
},
{
key: 2,
value: "baz"
},
{
key: 1000,
value: "something"
}
]
I got it to work but I was wondering if there's a less wordy way of doing this:
我得到了它的工作,但我想知道是否有一个不那么冗长的方式这样做:
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
4 个解决方案
#1
5
uniq
would work if you concatenate the arrays in reverse order:
如果以相反的顺序连接数组,uniq将起作用:
(b + a).uniq { |h| h[:key] }
#=> [
# {:key=>1, :value=>"bar"},
# {:key=>1000, :value=>"something"},
# {:key=>2, :value=>"baz"}
# ]
It doesn't however preserve the order.
但它不会保留订单。
#2
1
I would rebuild your data a bit, since there are redundant keys in hashes:
我会稍微重建你的数据,因为哈希中有冗余键:
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"}
Then you can use just Hash#merge
:
然后你就可以使用Hash#merge:
thin_a.merge(thin_b)
#=> {1=>"bar", 2=>"baz", 1000=>"something"}
But, if you want, you can get exactly result as mentioned in question:
但是,如果你愿意,你可以获得如上所述的确切结果:
result.map { |k, v| { key: k, value: v } }
#=> [{:key=>1, :value=>"bar"},
# {:key=>2, :value=>"baz"},
# {:key=>1000, :value=>"something"}]
#3
1
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
.reduce(&:merge)
.flat_map(&:last)
Here we use hash[:key]
as a key to build the new hash, then we merge
them overriding everything with the last value and return values
.
这里我们使用hash [:key]作为构建新哈希的键,然后我们将它们合并,用最后一个值覆盖所有内容并返回值。
#4
0
using Enumerable#group_by and Enumerable#map
使用Enumerable#group_by和Enumerable #map
(b+a).group_by { |e| e[:key] }.values.map {|arr| arr.first}
#1
5
uniq
would work if you concatenate the arrays in reverse order:
如果以相反的顺序连接数组,uniq将起作用:
(b + a).uniq { |h| h[:key] }
#=> [
# {:key=>1, :value=>"bar"},
# {:key=>1000, :value=>"something"},
# {:key=>2, :value=>"baz"}
# ]
It doesn't however preserve the order.
但它不会保留订单。
#2
1
I would rebuild your data a bit, since there are redundant keys in hashes:
我会稍微重建你的数据,因为哈希中有冗余键:
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"}
Then you can use just Hash#merge
:
然后你就可以使用Hash#merge:
thin_a.merge(thin_b)
#=> {1=>"bar", 2=>"baz", 1000=>"something"}
But, if you want, you can get exactly result as mentioned in question:
但是,如果你愿意,你可以获得如上所述的确切结果:
result.map { |k, v| { key: k, value: v } }
#=> [{:key=>1, :value=>"bar"},
# {:key=>2, :value=>"baz"},
# {:key=>1000, :value=>"something"}]
#3
1
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
.reduce(&:merge)
.flat_map(&:last)
Here we use hash[:key]
as a key to build the new hash, then we merge
them overriding everything with the last value and return values
.
这里我们使用hash [:key]作为构建新哈希的键,然后我们将它们合并,用最后一个值覆盖所有内容并返回值。
#4
0
using Enumerable#group_by and Enumerable#map
使用Enumerable#group_by和Enumerable #map
(b+a).group_by { |e| e[:key] }.values.map {|arr| arr.first}