Contador automático en rubí para cada uno?

134

Quiero usar un para cada uno y un contador:

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

Hay una mejor manera de hacerlo?

Nota: No sé si blahses una matriz o un hash, pero tener que hacerlo blahs[i]no lo haría mucho más sexy. También me gustaría saber cómo escribir i++en Ruby.


Técnicamente, la respuesta de Matt y Squeegy llegó primero, pero estoy dando la mejor respuesta a paradoja, así que difunde un poco los puntos en SO. También su respuesta tenía la nota sobre las versiones, que todavía es relevante (siempre que mi Ubuntu 8.04 esté usando Ruby 1.8.6).


Debería haber usado, puts "#{i} #{blah}"que es mucho más sucinto.

Dan Rosenstark
fuente
No hay operador de incremento en Ruby. El n + = 1 que escribió allí es el equivalente más cercano. Tendría que ser azúcar sintáctico para n + = 1, que en sí mismo es la abreviatura de n = n + 1. La idea de ++ fue rechazada porque oculta el hecho de que está reasignando la variable. rubyurl.com/Dsb1
Chuck
¡Agradable! Gracias Chuck Me vi obligado a aprender ++ i e i ++ en Java, así que pensé que siempre estaría allí.
Dan Rosenstark

Respuestas:

190

Como la gente ha dicho, puedes usar

each_with_index

pero si desea índices con un iterador diferente a "cada" (por ejemplo, si desea mapear con un índice o algo así) puede concatenar enumeradores con el método each_with_index, o simplemente usar with_index:

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

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

Esto es algo que puedes hacer desde Ruby 1.8.7 y 1.9.

paradoja
fuente
1
Vale la pena señalar que esto es nuevo en 1.9.
Zach Langley
1
Bien descrito. En realidad, también está en 1.8.7, pero es algo que vale la pena agregar.
paradoja
¿Por qué estoy en Ruby 1.8.6 si acabo de instalar todo en Ubuntu? ¿Es 1.8.7 experimental / beta?
Dan Rosenstark
¿Qué Ubuntu estás usando? En Intrepid hay 1.8.7. Es la última versión estable ( ruby-lang.org/en/downloads ). Sin embargo, es posible que monkeypatch ruby ​​1.8.6 tenga el mismo comportamiento (consulte strictlyuntyped.com/2008/09/ruby-187s-enumerator-class.html ).
paradoja
3
Me cansé de que la distribución estuviera detrás, así que comencé a usar rvm para administrar mi instalación de Ruby en Ubuntu y Linux Mint.
The Tin Man
55
[:a, :b, :c].each_with_index do |item, i|
  puts "index: #{i}, item: #{item}"
end

No puedes hacer esto con para. Generalmente me gusta la llamada más declarativa a cada uno personalmente de todos modos. En parte porque es fácil pasar a otras formas cuando alcanzas el límite de la sintaxis for.

Alex Wayne
fuente
Bien, veo el punto sobre los límites con la sintaxis for. Tengo que acostumbrarme a los bloques con múltiples parámetros.
Dan Rosenstark
11

Sí, es collection.eachhacer bucles y luego each_with_indexobtener el índice.

Probablemente deberías leer un libro de Ruby porque es Ruby fundamental y, si no lo sabes, tendrás grandes problemas (prueba: http://poignantguide.net/ruby/ ).

Tomado del código fuente 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
fuente
No hay problema, me alegro de ayudar. No quise ser "malo" con respecto a cada bloque. Estas son construcciones de rubí fundamentales y aprenderlas sobre la marcha será muy, muy doloroso. :) ¡Es mejor morder la bala y pasar unas horas leyendo!
Matt Rogish
6

Si no tiene la nueva versión de each_with_index, puede usar el zipmétodo para emparejar índices con elementos:

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

que produce:

1 one
2 two
3 three
4 four
5 five
Jorge
fuente
1
¿Dónde puedo encontrar este código en tu respuesta '%s %s' % [1, "two"]en los documentos de Ruby? Gracias por su ayuda y por conservar el espacio vertical utilizando una línea para comprimir y mapear.
Dan Rosenstark
1
En este contexto, el operador% -sign es un método de la clase String. Puede leer sobre esto en ruby-doc.org/core/classes/String.html#M000770 . O puede escribir ri String #% en el símbolo del sistema. O puede escribir ri% para ver todas las clases documentadas que lo reconocen, por ejemplo, el significado más familiar en ri Fixnum #%.
George
4

En cuanto a tu pregunta sobre cómo hacerlo i++, bueno, no puedes hacerlo en Ruby. La i += 1declaración que tenía es exactamente cómo se supone que debe hacerlo.

papa
fuente
1

Si blahses una clase que se mezcla en Enumerable, debería poder hacer esto:

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

Si desea obtener un índice de rubí para cada uno, puede usar

.each_with_index

Aquí hay un ejemplo para mostrar cómo .each_with_indexfunciona:

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

Esto imprimirá:

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
fuente