2013-03-07 9 views
13

Horuby: come trovare elementi non univoci nella matrice e stampare ciascuno con il numero di occorrenze?

a = ["a", "d", "c", "b", "b", "c", "c"] 

e la necessità di stampare qualcosa di simile (discendente ordinati secondo il numero di occorrenze):

c:3 
b:2 

ho capito prima parte (la ricerca non univoco) è:

b = a.select{ |e| a.count(e) > 1 } 
=> ["c", "b", "b", "c", "c"] 

o

puts b.select{|e, c| [e, a.count(e)] }.uniq 

c 
b 

Come stampare ogni non univoco con il numero di occorrenze ordinato all'indietro?

risposta

19
puts a.uniq. 
     map { | e | [a.count(e), e] }. 
     select { | c, _ | c > 1 }. 
     sort.reverse. 
     map { | c, e | "#{e}:#{c}" } 
+0

Molto elegante! Cosa rappresenta il "_"? Non l'ho visto prima. –

+3

@RichardBrown: un nome di variabile che in genere significa non utilizzato. – Linuxios

+0

Wow! Grazie! – earlyadopter

0

Questo vi darà un hash con element => occurrences:

b.reduce(Hash.new(0)) do |hash, element| 
    hash[element] += 1 
    hash 
end 
+1

Il blocco potrebbe essere messo un po 'più elegante: 'hash.update (elemento => hash [elemento] + 1)' –

6

Il metodo group_by viene utilizzato per questo spesso:

 
a.group_by{ |i| i } 
{ 
    "a" => [ 
     [0] "a" 
    ], 
    "d" => [ 
     [0] "d" 
    ], 
    "c" => [ 
     [0] "c", 
     [1] "c", 
     [2] "c" 
    ], 
    "b" => [ 
     [0] "b", 
     [1] "b" 
    ] 
} 

mi piace:

 
a.group_by{ |i| i }.each_with_object({}) { |(k,v), h| h[k] = v.size } 
{ 
    "a" => 1, 
    "d" => 1, 
    "c" => 3, 
    "b" => 2 
} 

Or :

 
Hash[a.group_by{ |i| i }.map{ |k,v| [k, v.size] }] 
{ 
    "a" => 1, 
    "d" => 1, 
    "c" => 3, 
    "b" => 2 
} 

Uno di quelli potrebbe graffiare il tuo prurito. Da lì è possibile ridurre il risultato usando un piccolo test:

 
Hash[a.group_by{ |i| i }.map{ |k,v| v.size > 1 && [k, v.size] }] 
{ 
    "c" => 3, 
    "b" => 2 
} 

Se si desidera solo per stampare la vendita Note:

 
puts a.group_by{ |i| i }.map{ |k,v| "#{k}: #{v.size}" } 
a: 1 
d: 1 
c: 3 
b: 2 
0
puts a.uniq. 
    map { |e| a.count(e) > 1 ? [e, a.count(e)] : nil }.compact. 
    sort { |a, b| b.last <=> a.last } 
+0

'a & a.uniq' è uguale a' a'. –

+2

@undur_gongor Non penso che lo sia, ma è come avere "a.uniq" ... In ogni caso, ho mantenuto i valori uniq anche nel mio codice, il che rende la domanda negativa e l'ho risolta. – oldergod

0
a.reduce(Hash.new(0)) { |memo,x| memo[x] += 1; memo } # Frequency count. 
    .select { |_,count| count > 1 } # Choose non-unique items. 
    .sort_by { |x| -x[1] } # Sort by number of occurrences descending. 
# => [["c", 3], ["b", 2]] 

anche:

a.group_by{|x|x}.map{|k,v|[k,v.size]}.select{|x|x[1]>1}.sort_by{|x|-x[1]} 
# => [["c", 3], ["b", 2]] 
0

Che ne dite di:

a.sort.chunk{|x| a.count(x)}.sort.reverse.each do |n, v| 
    puts "#{v[0]}:#{n}" if n > 1 
end 
1

Personalmente, come questa soluzione:

a.inject({}) {|hash, val| hash[val] ||= 0; hash[val] += 1; hash}. 
    reject{|key, value| value == 1}.sort.reverse. 
    each_pair{|k,v| puts("#{k}:#{v}")} 
Problemi correlati