2009-09-02 7 views

Répondre

14
types = Hash.new(-1) # It feels like this should be 0, but to be 
        # equivalent to your example it needs to be -1 
array.each do |c| 
    types[c.type] += 1 
end 
+0

+1 pour le commentaire. –

2

||= ne aide:

types = {} 
array.each do |c| 
    types[c.class] ||= 0 
    types[c.class] += 1 
end 
+2

Cela va le mettre à 1 la première fois à travers ... newarray [c.type] || = -1 newarray [c.type] + = 1 –

+0

Oui, n'est-ce pas ce que nous voulons? Par exemple, si array est [1] alors les types deviendront {Fixnum => 1}. Et nous avons 1 Fixnum. –

+0

Nous voulons qu'il soit mis à 0 à la fin de la boucle, pas 1, if! Types [c.class]. – Chuck

4
array.each do |c| 
    newarray[c.type] = 1 + (newarray[c.type] || -1) 
end 

Vous pouvez également

array.each do |c| 
    newarray[c.type] ||= -1 
    newarray[c.type] += 1 
end 
+1

J'aime votre deuxième. Le seul inconvénient est que c'est le genre de chose que quelqu'un qui viendra plus tard pourrait considérer comme une erreur. Si je l'utilise en production, j'ajouterai un petit commentaire expliquant pourquoi je le fais de cette façon. – Pesto

+0

J'aime la deuxième façon. Il s'agit de deux lignes et potentiellement de deux affectations, mais plus lisibles que les conditions complexes ou tout ce qui est poussé sur une ligne. – Chuck

6

Utilisez la méthode Array#fetch pour laquelle vous pouvez fournir une valeur par défaut si l'index n'existe pas:

array.each do |c| 
    newarray[c.type] = newarray.fetch(c.type, -1) + 1 
end 
0

Votre variable newarray est nommée bizarrement, puisque dans Ruby et dans la plupart des autres langages, les tableaux sont indexés par des entiers, pas des objets aléatoires comme Class. Il est plus probable que ce soit un Hash.

En outre, vous devez utiliser c.class, au lieu de c.type, qui est obsolète.

Enfin, puisque vous créez un Hash, vous pouvez utiliser inject comme ceci:

newarray = array.inject({}) do |h,c| 
    h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 
    h 
end 

Ou, pour une seule ligne:

newarray = array.inject({}) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h } 

Comme vous pouvez le voir, cela donne les résultats souhaités:

irb(main):001:0> array = [1, {}, 42, [], Object.new(), [1, 2, 3]] 
=> [1, {}, 42, [], #<Object:0x287030>, [1, 2, 3]] 
irb(main):002:0> newarray = array.inject({}) { |h,c| h[c.class] = h.key?(c.class) ? h[c.class]+1 : 0 ; h } 
=> {Object=>0, Hash=>0, Array=>1, Fixnum=>1} 
0

En Ruby 1.8.7 ou version ultérieure, vous pouvez utiliser group_by, puis transformez chaque liste d'éléments en nombre-1 et créez un hachage à partir du tableau renvoyé par map.

Hash[array.group_by(&:class).map { |k,v| [k, v.size-1] }] 
Questions connexes