这是将要处理的数组:
[{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
我希望结果如下:
[{:name => "blake", :count => 2}, {:name => "ashley", :count => 1}]
我创建了一个名为" count"的新哈希然后我使用.each
遍历数组,然后count[:count] += 1
,但它没有给我我正在寻找的东西。
答案 0 :(得分:7)
可以使用内置库调用来完成:
a = [{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
a.group_by(&:itself) # group all of the identical elements together
.map{|k, v| k.merge(count: v.length)} # add the "count" element to the hash
.group_by(&:itself)
将获取所有相同的组件,并将它们放在同一密钥下的哈希值中:
>> h = a.group_by(&:itself)
=> {
{:name=>"blake"} => [{:name=>"blake"}, {:name=>"blake"}],
{:name=>"ashley"} => [{:name=>"ashley"}]
}
注意哈希中的第一个条目如何具有两个相同元素的数组,第二个条目具有一个元素的数组。要创建那些计数,我们可以在哈希值的数组上使用.length
方法:
>> k, v = h.first
>> v
=> [{:name=>"blake"}, {:name=>"blake"}]
>> v.length
=> 2
然后我们可以使用.map
将该代码应用于散列中的每个元素:
>> h.map{|k, v| [k, v.length]}.to_h
=> {
{:name=>"blake"}=>2,
{:name=>"ashley"}=>1
}
最后,.merge
将采用两个哈希并将它们组合成一个哈希:
>> {:name=>"blake"}.merge({:count => 1})
=> {:name=>"blake", :count=>1}
答案 1 :(得分:1)
以下是 Ruby 2.7.0 引入的新Enumerable#tally:
h = [{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
h.tally.map {|k, v| k.merge({count: v}) }
#=> [{:name=>"blake", :count=>2}, {:name=>"ashley", :count=>1}]
答案 2 :(得分:0)
这有三种主要方法。
这就是@ user12341234在他或她的回答中所做的。
使用计数哈希
如果您的数组是arr
,
arr.each_with_object(Hash.new(0)) { |g,h| h[g[:name]] += 1 }.
map { |name, count| { :name=>name, :count=>count } }
#=> [{:name=>"blake", :count=>2}, {:name=>"ashley", :count=>1}]
有关详细信息,请参阅Hash::new。
使用Hash#update
(aka merge!
)的形式使用块来确定合并的两个哈希中存在的键的值。
arr.each_with_object({}) { |g,h| h.update(g[:name]=>1) { |_,o,n| o+n } }.
map { |name, count| { :name=>name, :count=>count } }
#=> [{:name=>"blake", :count=>2}, {:name=>"ashley", :count=>1}]
有关详细信息,请参阅文档Hash#update。
请注意,#2和#3的最后一行是相同的。
我不能说其中一种方法比其他方法更好。