Compteur automatique en Ruby pour chacun?

134

Je veux utiliser un pour-chacun et un compteur:

i=0
for blah in blahs
    puts i.to_s + " " + blah
    i+=1
end

Y a-t-il une meilleure façon de le faire?

Remarque: je ne sais pas s'il blahss'agit d'un tableau ou d'un hachage, mais devoir le faire ne le blahs[i]rendrait pas beaucoup plus sexy. J'aimerais aussi savoir comment écrire i++en Ruby.


Techniquement, la réponse de Matt et Squeegy est arrivée en premier, mais je donne la meilleure réponse à paradoja, alors répartissez un peu les points sur SO. Sa réponse avait également la note sur les versions, qui est toujours pertinente (tant que mon Ubuntu 8.04 utilise Ruby 1.8.6).


J'aurais dû utiliser puts "#{i} #{blah}"ce qui est beaucoup plus succinct.

Dan Rosenstark
la source
Il n'y a pas d'opérateur d'incrémentation dans Ruby. Le n + = 1 que vous avez écrit ici est l'équivalent le plus proche. Il faudrait que ce soit du sucre syntaxique pour n + = 1, qui est lui-même un raccourci pour n = n + 1. L'idée de ++ a été rejetée car elle cache le fait que vous réaffectez la variable. rubyurl.com/Dsb1
Chuck
Agréable! Merci Chuck. J'ai été obligé d'apprendre ++ i et i ++ en Java, alors j'ai juste pensé que ce serait toujours là.
Dan Rosenstark le

Réponses:

190

Comme les gens l'ont dit, vous pouvez utiliser

each_with_index

mais si vous voulez des index avec un itérateur différent de "each" (par exemple, si vous voulez mapper avec un index ou quelque chose comme ça), vous pouvez concaténer les énumérateurs avec la méthode each_with_index, ou simplement utiliser with_index:

blahs.each_with_index.map { |blah, index| something(blah, index)}

blahs.map.with_index { |blah, index| something(blah, index) }

C'est quelque chose que vous pouvez faire à partir de ruby ​​1.8.7 et 1.9.

Paradoja
la source
1
Il convient de noter que c'est nouveau dans la version 1.9.
Zach Langley
1
Bien repéré. En fait, c'est aussi en 1.8.7, mais c'est quelque chose qui vaut la peine d'être ajouté.
paradoja
pourquoi suis-je sur Ruby 1.8.6 si je viens d'installer le tout sur Ubuntu? Le 1.8.7 est-il expérimental / bêta?
Dan Rosenstark le
Quel Ubuntu utilisez-vous? Dans Intrepid, il y a 1.8.7. C'est la dernière version stable ( ruby-lang.org/en/downloads ). Vous pouvez, cependant, monkeypatch ruby ​​1.8.6 pour avoir le même comportement (voir strictementuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
paradoja
3
J'étais fatigué de la distribution derrière alors j'ai commencé à utiliser rvm pour gérer mon installation Ruby sur Ubuntu et Linux Mint.
the Tin Man
55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

Vous ne pouvez pas faire ça avec pour. J'aime généralement l'appel plus déclaratif à chacun personnellement de toute façon. En partie parce qu'il est facile de passer à d'autres formes lorsque vous atteignez la limite de la syntaxe for.

Alex Wayne
la source
Bien, je vois le point sur les limites avec la syntaxe for. Je dois m'habituer aux blocs avec plusieurs paramètres.
Dan Rosenstark
11

Oui, c'est collection.eachpour faire des boucles, puis each_with_indexpour obtenir l'index.

Vous devriez probablement lire un livre Ruby car c'est Ruby fondamental et si vous ne le savez pas, vous allez avoir de gros problèmes (essayez: http://poignantguide.net/ruby/ ).

Tiré du code source de Ruby:

 hash = Hash.new
 %w(cat dog wombat).each_with_index {|item, index|
   hash[item] = index
 }
 hash   #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
Matt Rogish
la source
Pas de problème, heureux de vous aider. Je ne voulais pas être "méchant" à propos du bloc .each - ce sont des constructions rubis fondamentales et les apprendre à la volée sera vraiment, vraiment douloureux. :) Mieux vaut mordre la balle et passer quelques heures à lire!
Matt Rogish
6

Si vous ne disposez pas de la nouvelle version de each_with_index, vous pouvez utiliser la zipméthode pour associer des index avec des éléments:

blahs = %w{one two three four five}
puts (1..blahs.length).zip(blahs).map{|pair|'%s %s' % pair}

qui produit:

1 one
2 two
3 three
4 four
5 five
George
la source
1
Où puis-je trouver ce code à partir de votre réponse '%s %s' % [1, "two"]dans la documentation Ruby? Merci pour votre aide et pour la conservation de l'espace vertical en utilisant une seule ligne pour la fermeture éclair et la cartographie.
Dan Rosenstark
1
Dans ce contexte, l'opérateur% -sign est une méthode de la classe String. Vous pouvez en savoir plus sur ruby-doc.org/core/classes/String.html#M000770 . Ou vous pouvez taper ri String #% à une invite de commandes. Ou vous pouvez taper ri% pour voir toutes les classes documentées qui le reconnaissent, par exemple, la signification plus familière à ri Fixnum #%.
George
4

Quant à votre question sur le faire i++, eh bien, vous ne pouvez pas le faire dans Ruby. La i += 1déclaration que vous avez faite est exactement comment vous êtes censé le faire.

le pape
la source
1

S'il blahss'agit d'une classe qui se mélange dans Enumerable, vous devriez pouvoir le faire:

blahs.each_with_index do |blah, i|
  puts("#{i} #{blah}")
end
Roy Pardee
la source
1

Si vous souhaitez obtenir un index de rubis pour chacun, vous pouvez utiliser

.each_with_index

Voici un exemple pour montrer comment .each_with_indexfonctionne:

range = ('a'..'z').to_a
length = range.length - 1
range.each_with_index do |letter, index|
    print letter + " "
    if index == length
        puts "You are at last item"
    end
end

Cela imprimera:

a b c d e f g h i j k l m n o p q r s t u v w x y z You are at last item
Ilyas Karim
la source