13

我有两个哈希数组:

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

5 回答 5

15

uniq如果您以相反的顺序连接数组,则将起作用:

(b + a).uniq { |h| h[:key] }
#=> [
#     {:key=>1, :value=>"bar"},
#     {:key=>1000, :value=>"something"},
#     {:key=>2, :value=>"baz"}
#   ]

但是,它不会保留顺序。

于 2017-04-28T17:30:09.523 回答
2
[a, b].map { |arr| arr.group_by { |e| e[:key] } }
      .reduce(&:merge)
      .flat_map(&:last)

在这里,我们使用hash[:key]作为构建新哈希的键,然后我们merge用最后一个值覆盖所有内容并返回values

于 2017-04-28T17:25:18.710 回答
1

我会重建你的数据,因为哈希中有冗余键:

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"}]
于 2017-04-28T17:40:07.533 回答
0

使用Enumerable#group_byEnumerable#map

(b+a).group_by { |e| e[:key] }.values.map {|arr| arr.first}
于 2017-04-28T19:13:56.013 回答
0

如果您需要合并两个也应该合并的哈希数组并且有两个以上的键,那么下一个片段应该会有所帮助:

[a, b].flatten
      .compact
      .group_by { |v| v[:key] }
      .values
      .map { |e| e.reduce(&:merge) }
于 2020-11-30T13:44:54.123 回答