2009-11-19 8 views

Répondre

28

Cela donnera les éléments en double comme un hachage avec le nombre d'occurences pour chaque élément en double. Laissez le code parler:

#!/usr/bin/env ruby 

class Array 
    # monkey-patched version 
    def dup_hash 
    inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { 
     |k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r } 
    end 
end 

# unmonkeey'd 
def dup_hash(ary) 
    ary.inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { 
    |_k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r } 
end 

p dup_hash([1, 2, "a", "a", 4, "a", 2, 1]) 
# {"a"=>3, 1=>2, 2=>2} 

p [1, 2, "Thanks", "You're welcome", "Thanks", 
    "You're welcome", "Thanks", "You're welcome"].dup_hash 
# {"You're welcome"=>3, "Thanks"=>3} 
+1

-1 pour un patch de singe inutile. –

+3

thx. answer inclut maintenant une version non-sing-patched. – miku

+1

Non plus -1, mais sérieusement ... ne pas corriger le singe à moins qu'il n'y ait pas d'autre moyen de le faire. –

2

Je ne pense pas qu'il existe une méthode intégrée. Si tout ce dont vous avez besoin est le total nombre de doublons, vous pouvez prendre un.length - un.uniq.length. Si vous recherchez le nombre d'un élément particulier, essayez
a.select {|e| e == my_element}.length.

14

Simple.

arr = [2,3,4,3,2,67,2] 
repeats = arr.length - arr.uniq.length 
puts repeats 
+0

Merci! Cela a bien fonctionné pour moi. Je n'arrête pas d'oublier uniq .... – CalebHC

7

1.8.7+ nécessite pour group_by

ary = %w{a b c d a e f g a h i b} 
ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.map{|key,val| key} 
# => ["a", "b"] 

avec 1.9+ cela peut être légèrement simplifiée car # Hash select retournera un hachage.

ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.keys 
# => ["a", "b"] 
50

Une autre version d'un hachage avec une clé pour chaque élément de votre tableau et la valeur pour le compte de chaque élément

a = [ 1, 2, 3, 3, 4, 3] 
h = Hash.new(0) 
a.each { | v | h.store(v, h[v]+1) } 

# h = { 3=>3, 2=>1, 1=>1, 4=>1 } 
+24

+1. Plus d'élégance - 'a.each {| v | h [v] + = 1} ' –

+3

En tant que ligne simple:' [1, 2, 3, 3, 4, 3] .reduce (Hash.new (0)) {| h, v | h.store (v, h [v] + 1); h} '. '# reduce' est généralement préféré à un' # each' utilisé pour remplir une nouvelle variable. –

+0

C'est la solution la plus propre qui colle aux agrafes de méthode Ruby. Je voudrais juste souligner que cela fonctionne également pour les tableaux mixtes et, dans Ruby, tout objet peut être une clé! Essayez de compter: [: a,: b,: a, 1, 10, 10, "b", "Bob", "Bob", "Bobby"]. En fait, cela fonctionne. – Usagi

3

Pour compter les occurrences d'un usage unique élément injection

array.inject(0){|count,elem| elem == value ? count+1 : count} 
30

Étant donné:

arr = [ 1, 2, 3, 2, 4, 5, 3] 

M y façon préférée des éléments de comptage est:

counts = arr.group_by{|i| i}.map{|k,v| [k, v.count] } 

# => [[1, 1], [2, 2], [3, 2], [4, 1], [5, 1]] 

Si vous avez besoin d'un hachage au lieu d'un tableau:

Hash[*counts.flatten] 

# => {1=>1, 2=>2, 3=>2, 4=>1, 5=>1} 
3

Qu'en est-il un grep?

arr = [1, 2, "Thanks", "You're welcome", "Thanks", "You're welcome", "Thanks", "You're welcome"] 

arr.grep('Thanks').size # => 3 
11
arr = %w(a b c d c b a) 
# => ["a", "b", "c", "d", "c", "b", "a"] 

arr.count('a') 
# => 2 
+4

Cette méthode est de loin la meilleure solution. C'est pourquoi nous utilisons Ruby! –

1

Il est facile:

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

Une ligne solution est simple:

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

Il fonctionne pour moi.

Merci!

9

Une autre manière de compter les doublons de tableau est la suivante:

arr= [2,2,3,3,2,4,2] 

arr.group_by{|x| x}.map{|k,v| [k,v.count] } 
résultat

est

[[2, 4], [3, 2], [4, 1]]

2

Amélioration @ la réponse de Kim:

arr = [1, 2, "a", "a", 4, "a", 2, 1] 
Hash.new(0).tap { |h| arr.each { |v| h[v] += 1 } } 
# => {1=>2, 2=>2, "a"=>3, 4=>1} 
0

Je l'ai utilisé reduce/inject pour cela dans le passé, comme le suivant

array = [1,5,4,3,1,5,6,8,8,8,9] 
array.reduce (Hash.new(0)) {|counts, el| counts[el]+=1; counts} 

produit

=> {1=>2, 5=>2, 4=>1, 3=>1, 6=>1, 8=>3, 9=>1}