74 votes

compter les éléments en double dans un tableau ruby

J'ai un tableau trié comme ceci:

 ['FATAL <error title="Request timed out.">',
'FATAL <error title="Request timed out.">',
'FATAL <error title="There is insufficient system memory to run this query.">']
 

Je voudrais obtenir quelque chose comme ça (ne doit pas être un hash):

 [{:error => 'FATAL <error title="Request timed out.">', :count => 2}
{:error => 'FATAL <error title="There is insufficient system memory to run this query.">', :count => 1}]
 

137voto

nimrodm Points 9191

Le code suivant imprime ce que vous avez demandé. Je vous laisse choisir comment utiliser pour générer le hash que vous recherchez:

 # sample array
a=["aa","bb","cc","bb","bb","cc"]

# make the hash default to 0 so that += will work correctly
b = Hash.new(0)

# iterate over the array, counting duplicate entries
a.each do |v|
  b[v] += 1
end

b.each do |k, v|
  puts "#{k} appears #{v} times"
end
 

Note: Je viens de remarquer que vous avez dit que le tableau est déjà trié. Le code ci-dessus ne nécessite pas de tri. L'utilisation de cette propriété peut produire un code plus rapide.

69voto

vladr Points 34562

Vous pouvez le faire très succinctement (une ligne) en utilisant inject :

 a = ['FATAL <error title="Request timed out.">',
      'FATAL <error title="Request timed out.">',
      'FATAL <error title="There is insufficient ...">']

b = a.inject(Hash.new(0)) {|h,i| h[i] += 1; h }

b.to_a.each {|error,count| puts "#{count}: #{error}" }
 

Produira:

 1: FATAL <error title="There is insufficient ...">
2: FATAL <error title="Request timed out.">
 

31voto

Manish Shrivastava Points 4380

Si vous avez tableau comme ci-dessous. où le nombre d'éléments en double doit être effectué:

 words = ["aa","bb","cc","bb","bb","cc"]
 

Une solution simple en ligne est:

 result = words.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 }
 

Ça marche pour moi.

Merci!!

8voto

dan Points 9428

Personnellement je le ferais de cette façon:

 # myprogram.rb
a = ['FATAL <error title="Request timed out.">',
'FATAL <error title="Request timed out.">',
'FATAL <error title="There is insufficient system memory to run this query.">']
puts a
 

Ensuite, lancez le programme et dirigez-le vers uniq -c:

 ruby myprogram.rb | uniq -c
 

Sortie:

  2 FATAL <error title="Request timed out.">
 1 FATAL <error title="There is insufficient system memory to run this query.">
 

3voto

Milan Novota Points 10892
a = [1,1,1,2,2,3]
a.uniq.inject([]){|r, i| r << { :error => i, :count => a.select{ |b| b == i }.size } }
=> [{:count=>3, :error=>1}, {:count=>2, :error=>2}, {:count=>1, :error=>3}]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X