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.