如果指定键的值在数组中相同,如何合并散列

时间:2022-11-30 12:42:18

I have a array of hashes like this:

我有一系列像这样的哈希:

[ {:foo=>2, :date=>Sat, 01 Sep 2014},
 {:foo2=>2, :date=>Sat, 02 Sep 2014},
 {:foo3=>3, :date=>Sat, 01 Sep 2014},
 {:foo4=>4, :date=>Sat, 03 Sep 2014},
  {:foo5=>5, :date=>Sat, 02 Sep 2014}]

And I want to merge hashes if the :date are same. What I expect from the array above is:

如果:date相同,我想合并哈希值。我对上面的数组的期望是:

[ {:foo=>2, :foo3=>3, :date=>Sat, 01 Sep 2014},
 {:foo2=>2, :foo5=>5 :date=>Sat, 02 Sep 2014},
 {:foo4=>4, :date=>Sat, 03 Sep 2014}]

How can I do it?

我该怎么做?

Maybe should I reconsider data structure itself? For example should I use date value as a key of hash?

也许我应该重新考虑数据结构本身?例如,我应该使用日期值作为哈希的键吗?

2 个解决方案

#1


8  

Here's how you could do it in a line (demo):

这是你如何在一行(演示)中做到这一点:

hashes.group_by{|h| h[:date] }.map{|_, hs| hs.reduce(:merge)}

This code does the following:

此代码执行以下操作:

  • groups all hashes by their :date value
  • 按以下方式对所有哈希值进行分组:日期值

  • for each :date group, takes all hashes in it and merges them all into one hash
  • 对于每个:日期组,获取其中的所有哈希值并将它们全部合并为一个哈希值

EDIT: Applied modifications suggested by tokland and Cary Swoveland. Thanks!

编辑:由tokland和Cary Swoveland提出的应用修改。谢谢!

#2


0  

You could make use of the form of Hash#update (a.k.a. merge!) that uses a block to resolve the values of keys that are contained in both of the hashes being merged.

您可以使用Hash#update(a.k.a。merge!)的形式,它使用块来解析合并的两个哈希中包含的键的值。

arr = [ {:foo=>2, :date=>'Sat, 01 Sep 2014'},
        {:foo2=>2, :date=>'Sat, 02 Sep 2014'},
        {:foo3=>3, :date=>'Sat, 01 Sep 2014'},
        {:foo4=>4, :date=>'Sat, 03 Sep 2014'},
        {:foo5=>5, :date=>'Sat, 02 Sep 2014'}]

arr.each_with_object({}) do |g,h|
  h.update({ g[:date]=>g }) { |_,o,n| o.merge(n) }
end.values
  #=> [{:foo=>2,  :date=>"Sat, 01 Sep 2014", :foo3=>3},
  #    {:foo2=>2, :date=>"Sat, 02 Sep 2014", :foo5=>5},
  #    {:foo4=>4, :date=>"Sat, 03 Sep 2014"}]

I've used a placeholder _ for the block variable containing the value of the key since it it not used in the block.

我已经使用占位符_作为包含键值的块变量,因为它没有在块中使用。

#1


8  

Here's how you could do it in a line (demo):

这是你如何在一行(演示)中做到这一点:

hashes.group_by{|h| h[:date] }.map{|_, hs| hs.reduce(:merge)}

This code does the following:

此代码执行以下操作:

  • groups all hashes by their :date value
  • 按以下方式对所有哈希值进行分组:日期值

  • for each :date group, takes all hashes in it and merges them all into one hash
  • 对于每个:日期组,获取其中的所有哈希值并将它们全部合并为一个哈希值

EDIT: Applied modifications suggested by tokland and Cary Swoveland. Thanks!

编辑:由tokland和Cary Swoveland提出的应用修改。谢谢!

#2


0  

You could make use of the form of Hash#update (a.k.a. merge!) that uses a block to resolve the values of keys that are contained in both of the hashes being merged.

您可以使用Hash#update(a.k.a。merge!)的形式,它使用块来解析合并的两个哈希中包含的键的值。

arr = [ {:foo=>2, :date=>'Sat, 01 Sep 2014'},
        {:foo2=>2, :date=>'Sat, 02 Sep 2014'},
        {:foo3=>3, :date=>'Sat, 01 Sep 2014'},
        {:foo4=>4, :date=>'Sat, 03 Sep 2014'},
        {:foo5=>5, :date=>'Sat, 02 Sep 2014'}]

arr.each_with_object({}) do |g,h|
  h.update({ g[:date]=>g }) { |_,o,n| o.merge(n) }
end.values
  #=> [{:foo=>2,  :date=>"Sat, 01 Sep 2014", :foo3=>3},
  #    {:foo2=>2, :date=>"Sat, 02 Sep 2014", :foo5=>5},
  #    {:foo4=>4, :date=>"Sat, 03 Sep 2014"}]

I've used a placeholder _ for the block variable containing the value of the key since it it not used in the block.

我已经使用占位符_作为包含键值的块变量,因为它没有在块中使用。