2009-02-10 8 views
125

Voglio usare una for-each e un contatore:Contatore automatico in Ruby per ciascuno?

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

Esiste un modo migliore per farlo?

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


Tecnicamente, la risposta di Squeegy di Matt ed è venuto in prima, ma sto dando risposta migliore per paradoja in modo diffuso in tutto i punti un po 'su SO. Anche la sua risposta ha la nota sulle versioni, che è ancora rilevante (purché la mia Ubuntu 8.04 stia usando Ruby 1.8.6).


dovrebbe aver utilizzato puts "#{i} #{blah}" che è molto più succinta.

+0

Non v'è alcun operatore di incremento in Ruby. Il n + = 1 che hai scritto è l'equivalente più vicino. Dovrebbe essere lo zucchero sintattico per n + = 1, che è esso stesso abbreviazione di n = n + 1. L'idea di ++ è stata respinta perché nasconde il fatto che stai riassegnando la variabile. http://rubyurl.com/Dsb1 – Chuck

+0

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

risposta

183

Come è già stato detto, è possibile utilizzare

each_with_index 

ma se si vuole indici con un iteratore diverso da "ciascuno" (ad esempio, se si desidera mappare con un indice o qualcosa del genere) è possibile concatenare gli enumeratori con il metodo each_with_index, o semplicemente utilizzare 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 da Ruby 1.8.7 e 1.9.

+1

Vale la pena notare che questo è nuovo nel 1.9. –

+1

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

+0

perché sono su Ruby 1.8.6 se ho appena installato il tutto su Ubuntu? 1.8.7 sperimentale/beta? –

10

Sì, è collection.each fare loop, quindi each_with_index per ottenere l'indice.

Probabilmente dovresti leggere un libro Ruby perché questo è fondamentale Ruby e se non lo sai, sarai nei guai (prova: http://poignantguide.net/ruby/).

tratti 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} 
+0

Grazie per il link (eccellente) e la risposta. –

+0

Nessun problema, felice di aiutare. Non significava essere "mediocre" sul blocco .each - questi sono costrutti fondamentali per ruby ​​e impararli al volo sarà davvero, davvero doloroso. :) Meglio mordere la pallottola e passare qualche ora a leggere! –

+0

Nessun problema, grazie per la tua risposta, @Matt. –

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

Non si può fare questo con la. Di solito mi piace la chiamata più dichiarativa a ciascuno personalmente. In parte perché è facile passare ad altre forme quando raggiungi il limite della sintassi.

+0

Bello, vedo il punto sui limiti con la sintassi per. Devo abituarmi ai blocchi con più parametri. –

1

Se blahs è una classe che mescola in Enumerable, si dovrebbe essere in grado di fare questo:

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

Per quanto riguarda la tua domanda su come fare i++, beh, non puoi farlo in Ruby. L'affermazione i += 1 che hai avuto è esattamente come dovresti farlo.

+0

Cool, grazie, è stato trattato nei commenti sulla domanda ... –

6

Se non si dispone la nuova versione di each_with_index, è possibile utilizzare il metodo zip di accoppiare gli indici con 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," due "]' nei documenti Ruby? Grazie per il tuo aiuto e per la conservazione dello spazio verticale utilizzando una linea per lo zipping e la mappatura. –

+1

In questo contesto, l'operatore% -sign è un metodo della classe String. Puoi leggere a questo proposito su http://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 di ri Fixnum #%. – George

1

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

.each_with_index 

Ecco un n esempio per mostrare come .each_with_index opere:

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 

Verranno stampate:

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