2016-05-13 13 views
6

Posso contare un valore utilizzando Array#count.Come contare più valori in una matrice

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

Come posso contare più valori in un array?

Quello che ho scritto erano:

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

Penso che questi siano un po 'ridondante.

+0

Possibile duplicato di [Ruby: conta gli elementi univoci e le loro occorrenze in un array] (http://stackoverflow.com/questions/23294181/ruby-count-unique-elements-and-their-occurences-in-an- array) –

+1

La domanda nominata come un esempio è simile, ma non un duplicato corretto: quella domanda chiede come trovare il conteggio di ciascun elemento distinto, mentre questa domanda richiede la somma dei conteggi degli elementi selezionati. –

risposta

7

count può anche prendere un blocco, in modo da poter scrivere questo in un modo che attraversa solo l'array una volta:

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

o per divertimento, in un po 'più funzionale/point-free stile:

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

Vuoi dire qualcosa di carino come questo?

Mentre non c'è nulla nella libreria di base di Ruby che fornisce direttamente tale funzionalità, è piuttosto semplice aggiungerlo.

Si può solo scrivere metodo di supporto:

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 

Si potrebbe invece utilizzare Ruby nuova refinements per aggiungere un metodo per Array quando ne avete bisogno:

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 

Oppure si può scegliere di prendere la più percorso hacky e modificare Array direttamente:

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 

Abbiamo

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% 

Questo non è sorprendente se si considera che Array#- è codificato in C.

ho metodi non benchmark @ di Faraz come appaiono essere simili a @ Jtbandes.