2016-05-13 10 views
6

Mogę zliczyć wartość za pomocą Array#count.Jak liczyć wiele wartości w tablicy

numbers = [1, 2, 5, 5, 1, 3, 1, 2, 4, 3] 
numbers.count(1) #=> 3 

Jak zliczyć wiele wartości w tablicy?

Co napisałem były:

numbers.count(1) + numbers.count(2) #=> 5 
[1,2].map{|i| numbers.count(i)}.sum #=> 5 

Myślę, że są nieco zbędny.

+0

Możliwy duplikat [Ruby: Policz unikatowe elementy i ich wystąpienia w tablicy] (http://stackoverflow.com/questions/23294181/ruby-count-unique-elements-and-their-occurences-in-an- array) –

+1

Pytanie zadeklarowane jako przykład jest podobne, ale nie jest właściwym duplikatem: Pytanie to pyta, jak znaleźć liczbę każdego odrębnego elementu, podczas gdy to pytanie prosi o sumę zliczeń wybranych elementów. –

Odpowiedz

7

count mogą również blok, więc można napisać to w taki sposób, że tylko przemierza tablicę jednorazowo:

numbers.count {|i| [1,2].include? i } # => 5 

albo dla zabawy, w nieco bardziej funkcjonalnego/point-free stylu:

numbers.count &[1,2].method(:include?) # => 5 
2

Masz na myśli coś takiego?

[1, 2, 2, 3, 3, 3, 4, 4, 4, 4].count_all(3, 4) # => 7 

Chociaż nie ma nic w podstawowej bibliotece Ruby, która zapewnia tę funkcję bezpośrednio, dodanie tej funkcji jest całkiem banalne.

Mogłeś po prostu napisać metodę pomocnika:

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 

Można zamiast tego użyć Ruby nowego refinements dodać metodę Array kiedy trzeba go:

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 

Albo możesz zdecydować się podjąć bardziej hacky ścieżki i modyfikować Array bezpośrednio:

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 
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 

Mamy

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% 

To nie jest zaskakujące, biorąc pod uwagę, że Array#- jest kodowana w C.

zrobiłem metody nie Benchmark @ Faraz jako wydają się być podobne do @jtbandes'.

Powiązane problemy