I can count a value using Array#count
.
我可以使用Array#count计算一个值。
numbers = [1, 2, 5, 5, 1, 3, 1, 2, 4, 3]
numbers.count(1) #=> 3
How can I count multiple values in an array?
如何计算数组中的多个值?
What I wrote were:
我写的是:
numbers.count(1) + numbers.count(2) #=> 5
[1,2].map{|i| numbers.count(i)}.sum #=> 5
I think these are a bit redundant.
我认为这些有点多余。
3 个解决方案
#1
7
count
can also take a block, so you can write this in a way that only traverses the array once:
count也可以占用一个块,所以你可以用只遍历数组的方式写一次:
numbers.count {|i| [1,2].include? i } # => 5
Or for fun, in a slightly more functional/point-free style:
或者为了好玩,以更实用/无点的方式:
numbers.count &[1,2].method(:include?) # => 5
#2
2
You mean something pretty like this?
你的意思是这样的东西?
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
While there's nothing in Ruby's core library that provides that functionality directly, it's pretty trivial to add it.
虽然Ruby的核心库中没有直接提供该功能的东西,但添加它是非常简单的。
You could just write helper method:
你可以写辅助方法:
def count_all(array, values_to_count)
array.count { |el| values_to_count.include?(el) }
end
count_all([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], [3, 4]) # => 7
You could instead use Ruby's new refinements to add a method to Array
when you need it:
您可以使用Ruby的新改进在需要时向Array添加方法:
module ArrayExtensions
refine Array do
def count_all(*values_to_count)
self.count { |el| values_to_count.include?(el) }
end
end
end
# Then inside some module or class
using ArrayExtensions
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
Or you could opt to take the more hacky path and modify Array
directly:
或者您可以选择采用更多hacky路径并直接修改Array:
class Array
def count_all(*values_to_count)
self.count { |el| values_to_count.include?(el) }
end
end
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
#3
1
numbers = [1, 2, 5, 5, 1, 3, 1, 2, 4, 3]
numbers_to_count = [1, 2]
numbers.size - (numbers - numbers_to_count).size
#=> 5
We have
n = numbers.size
#=> 10
a = (numbers - numbers_to_count)
#=> [5, 5, 3, 4, 3]
m = a.size
#=> 5
n - m
#=> 5
require 'fruity'
n = 1e6
numbers = Array.new(n) { rand(100) }
#=> [21, 78, 20, 98,..., 41, 87, 57]
numbers.size
#=> 1000000
numbers_to_count = (0..99).to_a.sample(20)
#=> [80, 61, 43, 84, 16, 65, 7, 98, 59, 6,
# 58, 49, 1, 9, 94, 56, 13, 67, 22, 68]
compare do
_jtb1 { numbers.count {|i| numbers_to_count.include? i } }
_jtb2 { numbers.count &numbers_to_count.method(:include?) }
_cary { numbers.size - (numbers - numbers_to_count).size }
end
Running each test once. Test will take about 9 seconds.
_cary is faster than _jtb1 by 5x ± 1.0
_jtb1 is faster than _jtb2 by 10.000000000000009% ± 10.0%
This is not surprising considering that Array#- is coded in C.
考虑到Array# - 用C编码,这并不奇怪。
I didn't benchmark @faraz's methods as they appear to be similar to @jtbandes'.
我没有对@ faraz的方法进行基准测试,因为它们似乎与@jtbandes类似。
#1
7
count
can also take a block, so you can write this in a way that only traverses the array once:
count也可以占用一个块,所以你可以用只遍历数组的方式写一次:
numbers.count {|i| [1,2].include? i } # => 5
Or for fun, in a slightly more functional/point-free style:
或者为了好玩,以更实用/无点的方式:
numbers.count &[1,2].method(:include?) # => 5
#2
2
You mean something pretty like this?
你的意思是这样的东西?
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
While there's nothing in Ruby's core library that provides that functionality directly, it's pretty trivial to add it.
虽然Ruby的核心库中没有直接提供该功能的东西,但添加它是非常简单的。
You could just write helper method:
你可以写辅助方法:
def count_all(array, values_to_count)
array.count { |el| values_to_count.include?(el) }
end
count_all([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], [3, 4]) # => 7
You could instead use Ruby's new refinements to add a method to Array
when you need it:
您可以使用Ruby的新改进在需要时向Array添加方法:
module ArrayExtensions
refine Array do
def count_all(*values_to_count)
self.count { |el| values_to_count.include?(el) }
end
end
end
# Then inside some module or class
using ArrayExtensions
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
Or you could opt to take the more hacky path and modify Array
directly:
或者您可以选择采用更多hacky路径并直接修改Array:
class Array
def count_all(*values_to_count)
self.count { |el| values_to_count.include?(el) }
end
end
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7
#3
1
numbers = [1, 2, 5, 5, 1, 3, 1, 2, 4, 3]
numbers_to_count = [1, 2]
numbers.size - (numbers - numbers_to_count).size
#=> 5
We have
n = numbers.size
#=> 10
a = (numbers - numbers_to_count)
#=> [5, 5, 3, 4, 3]
m = a.size
#=> 5
n - m
#=> 5
require 'fruity'
n = 1e6
numbers = Array.new(n) { rand(100) }
#=> [21, 78, 20, 98,..., 41, 87, 57]
numbers.size
#=> 1000000
numbers_to_count = (0..99).to_a.sample(20)
#=> [80, 61, 43, 84, 16, 65, 7, 98, 59, 6,
# 58, 49, 1, 9, 94, 56, 13, 67, 22, 68]
compare do
_jtb1 { numbers.count {|i| numbers_to_count.include? i } }
_jtb2 { numbers.count &numbers_to_count.method(:include?) }
_cary { numbers.size - (numbers - numbers_to_count).size }
end
Running each test once. Test will take about 9 seconds.
_cary is faster than _jtb1 by 5x ± 1.0
_jtb1 is faster than _jtb2 by 10.000000000000009% ± 10.0%
This is not surprising considering that Array#- is coded in C.
考虑到Array# - 用C编码,这并不奇怪。
I didn't benchmark @faraz's methods as they appear to be similar to @jtbandes'.
我没有对@ faraz的方法进行基准测试,因为它们似乎与@jtbandes类似。