计算一个元素在数组中出现的次数 Ruby
Count how many times an element appears in an array in Ruby
这是要处理的数组:
[{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
我希望结果是这样的:
[{:name => "blake", :count => 2}, {:name => "ashley", :count => 1}]
我创建了一个名为 "count" 的新散列,然后我使用 .each
遍历数组然后 count[:count] += 1
,但它没有给我我要找的东西。
可以通过这样的内置库调用来完成:
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}
主要有三种方法。
这就是@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
(又名 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 的最后一行相同。
我不能说其中一种方法优于其他方法。
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}]
这是要处理的数组:
[{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
我希望结果是这样的:
[{:name => "blake", :count => 2}, {:name => "ashley", :count => 1}]
我创建了一个名为 "count" 的新散列,然后我使用 .each
遍历数组然后 count[:count] += 1
,但它没有给我我要找的东西。
可以通过这样的内置库调用来完成:
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}
主要有三种方法。
这就是@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
(又名 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 的最后一行相同。
我不能说其中一种方法优于其他方法。
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}]