Contatore automatico in Ruby per ciascuno?


134

Voglio usare un per-ciascuno e un contatore:

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

C'è un modo migliore per farlo?

Nota: non so se blahssia un array o un hash, ma doverlo fare blahs[i]non lo renderebbe molto più sexy. Inoltre mi piacerebbe sapere come scrivere i++in Ruby.


Tecnicamente, la risposta di Matt e Squeegy è arrivata per prima, ma sto dando la migliore risposta al paradosso, quindi spargo un po 'i punti su SO. Anche la sua risposta aveva la nota sulle versioni, che è ancora rilevante (purché il mio Ubuntu 8.04 stia usando Ruby 1.8.6).


Avrei dovuto usare quello puts "#{i} #{blah}"che è molto più succinto.


Non esiste un operatore di incremento in Ruby. Il n + = 1 che hai scritto lì è l'equivalente più vicino. Dovrebbe essere zucchero sintattico per n + = 1, che è di per sé una scorciatoia per n = n + 1. L'idea di ++ è stata respinta perché nasconde il fatto che stai riassegnando la variabile. rubyurl.com/Dsb1
Chuck,

Bello! Grazie Chuck. Sono stato costretto a imparare ++ ie i ++ in Java, quindi ho pensato che sarebbe sempre stato lì.
Dan Rosenstark,

Risposte:


190

Come le persone hanno detto, puoi usare

each_with_index

ma se vuoi indici con un iteratore diverso da "ciascuno" (ad esempio, se vuoi mappare con un indice o qualcosa del genere) puoi concatenare gli enumeratori con il metodo each_with_index, o semplicemente usare with_index:

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

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

Questo è qualcosa che puoi fare dal rubino 1.8.7 e 1.9.


1
Vale la pena notare che questo è nuovo in 1.9.
Zach Langley,

1
Ben individuato. In realtà, è anche in 1.8.7, ma è qualcosa che vale la pena aggiungere.
Paradoja,

perché sono su Ruby 1.8.6 se ho appena installato tutto su Ubuntu? 1.8.7 è sperimentale / beta?
Dan Rosenstark,

Quale Ubuntu stai usando? In Intrepid c'è 1.8.7. È l'ultima versione stabile ( ruby-lang.org/en/downloads ). Tuttavia, è possibile che monkeypatch ruby ​​1.8.6 abbia lo stesso comportamento (vedere strictuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
Paradoja,

3
Mi sono stancato della distribuzione, quindi ho iniziato a usare rvm per gestire la mia installazione di Ruby su Ubuntu e Linux Mint.
Tin Man,

55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

Non puoi farlo con per. Di solito mi piace comunque la chiamata più dichiarativa a ciascuno di loro. In parte perché è facile passare ad altre forme quando si raggiunge il limite della sintassi for.


Bene, vedo il punto sui limiti con la sintassi for. Devo abituarmi ai blocchi con più parametri.
Dan Rosenstark,

11

Sì, è collection.eachfare dei loop e quindi each_with_indexottenere l'indice.

Probabilmente dovresti leggere un libro di Ruby perché questo è Ruby fondamentale e se non lo conosci, avrai un grosso problema (prova: http://poignantguide.net/ruby/ ).

Tratto dal codice sorgente di Ruby:

 hash = Hash.new
 %w(cat dog wombat).each_with_index {|item, index|
   hash[item] = index
 }
 hash   #=> {"cat"=>0, "wombat"=>2, "dog"=>1}

Nessun problema, felice di aiutarti. Non intendevo essere "cattivi" con il blocco .each - questi sono fondamentali costrutti di rubini e impararli al volo sarà davvero, davvero doloroso. :) Meglio mordere il proiettile e passare qualche ora a leggere!
Matt Rogish,

6

Se non disponi della nuova versione di each_with_index, puoi utilizzare il zipmetodo per accoppiare gli indici agli elementi:

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

che produce:

1 one
2 two
3 three
4 four
5 five

1
Dove posso trovare questo codice dalla tua risposta '%s %s' % [1, "two"]nei documenti di Ruby? Grazie per il vostro aiuto e per conservare lo spazio verticale utilizzando una riga per zippare e mappare.
Dan Rosenstark,

1
In questo contesto, l'operatore% -sign è un metodo della classe String. Puoi leggerlo a ruby-doc.org/core/classes/String.html#M000770 . Oppure puoi digitare ri String #% al prompt dei comandi. Oppure puoi digitare ri% per vedere tutte le classi documentate che lo riconoscono, ad esempio il significato più familiare in Fixnum #%.
George,

4

Quanto alla tua domanda sul fare i++, beh, non puoi farlo in Ruby. L' i += 1affermazione che hai avuto è esattamente come dovresti farlo.



1

Se blahsè una classe che si mescola in Enumerable, dovresti essere in grado di farlo:

blahs.each_with_index do |blah, i|
  puts("#{i} #{blah}")
end

1

Se si desidera ottenere un indice di rubino per ciascuno, è possibile utilizzare

.each_with_index

Ecco un esempio per mostrare come .each_with_indexfunziona:

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

Questo stamperà:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.