Rails:如果特定键具有相同的值,如何合并两个哈希?

时间:2018-04-06 12:26:28

标签: ruby-on-rails ruby

如果特定键具有相同的值,我正在尝试合并哈希值。

这是数组

[{

  id: 77,
  member_phone: "9876543210",
  created_at: "2017-05-03T11:06:03.000Z",
  name: "Sure"
},
{
  id: 77,
  member_phone: "123456789",
  created_at: "2017-05-03T11:06:03.000Z",
  name: "Sure"
},
{
  id: 78,
  member_phone: "12345",
  created_at: "2017-05-03T11:06:03.000Z",
  name: "XYZ"
}]

和所需的输出:

[{
  id: 77,
  member_phone: "123456789,9876543210",
  created_at: "2017-05-03T11:06:03.000Z",
  name: "Sure"
},
{
  id: 78,
  member_phone: "12345",
  created_at: "2017-05-03T11:06:03.000Z",
  name: "XYZ"
}]

这是我试过的代码:

merge_users.group_by { |h1| h1["id"] }.map do |k,v|
  { "id" => k, :member_phone =>  v.map { |h2| h2[:member_phone] }.join(", ") }
end

我该怎么办?

3 个答案:

答案 0 :(得分:1)

以下代码适用于您的示例。

result = arr.group_by {|h| h[:id]}.values.map do |arr|
  arr.reduce do |h1, h2|
    h1.merge(h2) do |k, ov, nv|
      ov.eql?(nv) ? ov : [ov, nv].join(",")
    end
  end
end

结果

#=>[{:id=>77, :member_phone=>"9876543210,123456789", :created_at=>"2017-05-03T11:06:03.000Z", :name=>"Sure"}, {:id=>78, :member_phone=>"12345", :created_at=>"2017-05-03T11:06:03.000Z", :name=>"XYZ"}]

答案 1 :(得分:0)

怎么样:

grouped = data.group_by do |item|
  item[:id]
end

combined = grouped.map do |_id, hashes|
  hashes.inject({}) do |memo, hash|
    memo.merge(hash)
  end
end

它分两次通过:

首先按:id键的值对所有哈希值进行分组 这将返回一个Hash,其中id为键,一个数组(具有此id的所有哈希值)作为值。

在第二遍中,所有哈希值都会合并并再次映射到数组。

答案 2 :(得分:0)

arr = [
  { id: 77, phone: "9876543210", name: "Sure" },
  { id: 77, phone: "123456789", name: "Sure" },
  { id: 78, phone: "12345", name: "XYZ" }
]

您可以使用Hash#update(又名merge!)的形式,该形式使用块来计算合并的两个哈希中存在的键的值。

arr.each_with_object({}) { |g,h| h.update(g[:id]=>g) { |_,o,n|
  o.merge(phone: "#{o[:phone]}#{n[:phone]}") } }.values
  #=> [{:id=>77, :phone=>"9876543210123456789", :name=>"Sure"},
  #    {:id=>78, :phone=>"12345", :name=>"XYZ"}]

请注意Hash#values的接收者如下。

#=> {77=>{:id=>77, :phone=>"9876543210123456789", :name=>"Sure"},
#    78=>{:id=>78, :phone=>"12345", :name=>"XYZ"}}

有关三个块变量Hash#update_o的定义,请参阅n的文档。我使用下划线表示第一个变量(局部变量的有效名称),表示它不用于块计算(通常的做法)。

请注意,Hash#update几乎可以在Enumerable#group_by可以使用时使用,反之亦然。

这是在这里使用Hash#group_by的一种方式。

arr.group_by { |h| h[:id] }.
    map { |_,a| a.first.merge(phone: a.map { |h| h[:phone] }.join) }
  #=> [{:id=>77, :phone=>"9876543210123456789", :name=>"Sure"},
  #    {:id=>78, :phone=>"12345", :name=>"XYZ"}]         

请注意

arr.group_by { |h| h[:id] }
  #=> {77=>[{:id=>77, :phone=>"9876543210", :name=>"Sure"},
  #         {:id=>77, :phone=>"123456789", :name=>"Sure"}],
  #    78=>[{:id=>78, :phone=>"12345", :name=>"XYZ"}]}