Как объединить два массива хэшей
У меня есть два массива хэшей:
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
4 ответа
uniq
будет работать, если вы объедините массивы в обратном порядке:
(b + a).uniq { |h| h[:key] }
#=> [
# {:key=>1, :value=>"bar"},
# {:key=>1000, :value=>"something"},
# {:key=>2, :value=>"baz"}
# ]
Это, однако, не сохраняет порядок.
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
.reduce(&:merge)
.flat_map(&:last)
Здесь мы используем hash[:key]
в качестве ключа для создания нового хэша, то мы merge
они перекрывают все с последним значением и возвращают values
,
Я бы немного перестроил ваши данные, так как в хешах есть избыточные ключи:
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 и 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) }