PHP, para todas sus verrugas, es bastante bueno en este aspecto. No hay diferencia entre una matriz y un hash (tal vez soy ingenuo, pero esto obviamente me parece correcto), y para iterar o simplemente
foreach (array/hash as $key => $value)
En Ruby hay muchas maneras de hacer este tipo de cosas:
array.length.times do |i|
end
array.each
array.each_index
for i in array
Los hashes tienen más sentido, ya que siempre uso
hash.each do |key, value|
¿Por qué no puedo hacer esto para matrices? Si quiero recordar solo un método, creo que puedo usarlo each_index
(ya que hace que tanto el índice como el valor estén disponibles), pero es molesto tener que hacerlo en array[index]
lugar de solo value
.
Oh cierto, me olvidé array.each_with_index
. Sin embargo, este apesta porque va |value, key|
y hash.each
va |key, value|
! ¿No es esto una locura?
array#each_with_index
usa|value, key|
porque el nombre del método implica el orden, mientras que el orden utilizado parahash#each
imita lahash[key] = value
sintaxis.Respuestas:
Esto iterará a través de todos los elementos:
Huellas dactilares:
Esto iterará a través de todos los elementos que le dan el valor y el índice:
Huellas dactilares:
No estoy muy seguro de su pregunta cuál está buscando.
fuente
Creo que no hay una sola manera correcta . Hay muchas formas diferentes de iterar, y cada una tiene su propio nicho.
each
es suficiente para muchos usos, ya que a menudo no me importan los índices.each_ with _index
actúa como Hash # cada uno: obtienes el valor y el índice.each_index
- Solo los índices. No uso este a menudo. Equivalente a "length.times".map
es otra forma de iterar, útil cuando quieres transformar una matriz en otra.select
es el iterador para usar cuando desea elegir un subconjunto.inject
es útil para generar sumas o productos, o para recopilar un solo resultado.Puede parecer mucho recordar, pero no se preocupe, puede sobrevivir sin conocerlos todos. Pero a medida que comience a aprender y usar los diferentes métodos, su código se volverá más y más claro, y estará en camino hacia el dominio de Ruby.
fuente
No digo que
Array
->|value,index|
yHash
->|key,value|
no sea una locura (ver el comentario de Horace Loeb), pero sí digo que hay una forma sensata de esperar este acuerdo.Cuando trato con matrices, me centro en los elementos de la matriz (no en el índice porque el índice es transitorio). El método es cada uno con índice, es decir, cada + índice, o | cada, índice | o
|value,index|
. Esto también es coherente con el índice visto como un argumento opcional, por ejemplo | valor | es equivalente a | value, index = nil | que es consistente con | value, index |.Cuando estoy tratando con hashes, a menudo estoy más enfocado en las claves que en los valores, y generalmente estoy tratando con claves y valores en ese orden, ya sea
key => value
ohash[key] = value
.Si desea escribir pato, entonces explícitamente use un método definido como mostró Brent Longborough, o un método implícito como mostró maxhawkins.
Ruby tiene que ver con acomodar el lenguaje para adaptarse al programador, no para que el programador se adapte al lenguaje. Por eso hay tantas formas. Hay muchas maneras de pensar en algo. En Ruby, eliges el más cercano y el resto del código generalmente se cae de manera extremadamente clara y concisa.
En cuanto a la pregunta original, "¿Cuál es la forma" correcta "de iterar a través de una matriz en Ruby?" Bueno, creo que la forma central (es decir, sin poder sintáctico potente o poder orientado a objetos) es hacer:
Pero Ruby tiene que ver con el poderoso azúcar sintáctico y el poder orientado a objetos, pero de todos modos aquí es el equivalente para los hashes, y las claves se pueden ordenar o no:
Entonces, mi respuesta es: "La forma" correcta "de recorrer una matriz en Ruby depende de usted (es decir, del programador o del equipo de programación) y del proyecto". El mejor programador de Ruby hace la mejor elección (de qué poder sintáctico y / o qué enfoque orientado a objetos). El mejor programador de Ruby continúa buscando más formas.
Ahora, quiero hacer otra pregunta, "¿Cuál es la forma" correcta "de recorrer un rango en Ruby hacia atrás?" (Esta pregunta es cómo llegué a esta página).
Es bueno hacer (para los delanteros):
pero no me gusta hacer (al revés):
Bueno, en realidad no me importa hacer eso demasiado, pero cuando enseño hacia atrás, quiero mostrarles a mis estudiantes una buena simetría (es decir, con una diferencia mínima, por ejemplo, solo agregando un reverso o un paso -1, pero sin modificando cualquier otra cosa). Puedes hacer (por simetría):
y
que no me gusta mucho, pero no puedes hacer
En última instancia, podrías hacer
pero quiero enseñar Ruby puro en lugar de enfoques orientados a objetos (todavía). Me gustaría repetir al revés:
Creo que esto es imposible sin definir un
pred
método, lo que significa modificar la clase Range para usarlo. Si puede hacer esto, hágamelo saber, de lo contrario se agradecería la confirmación de imposibilidad, aunque sería decepcionante. Quizás Ruby 1.9 aborde esto.(Gracias por tu tiempo leyendo esto).
fuente
1.upto(10) do |i| puts i end
y10.downto(1) do puts i end
le da la simetría que deseaba. Espero que ayude. No estoy seguro de si funcionaría para cadenas y tal.[*1..10].each{|i| puts "i=#{i}" }
.Use each_with_index cuando necesite ambos.
fuente
Las otras respuestas están bien, pero quería señalar otra cosa periférica: las matrices están ordenadas, mientras que los hashes no están en 1.8. (En Ruby 1.9, los hashes se ordenan por orden de inserción de claves.) Por lo tanto, no tendría sentido antes de 1.9 iterar sobre un hash de la misma manera / secuencia que las matrices, que siempre han tenido un orden definido. No sé cuál es el orden predeterminado para las matrices asociativas de PHP (aparentemente mi Google Fu tampoco es lo suficientemente fuerte como para descubrir eso), pero no sé cómo puede considerar las matrices PHP regulares y las matrices asociativas PHP para ser "lo mismo" en este contexto, ya que el orden de las matrices asociativas parece indefinido.
Como tal, la forma Ruby me parece más clara e intuitiva. :)
fuente
Intentar hacer lo mismo de manera consistente con las matrices y los hashes podría ser solo un olor a código, pero, a riesgo de que me tilden de medio parche codoroso, si buscas un comportamiento coherente, ¿funcionaría? ?:
fuente
Aquí están las cuatro opciones enumeradas en su pregunta, ordenadas por libertad de control. Es posible que desee utilizar uno diferente dependiendo de lo que necesite.
Simplemente ve a través de los valores:
Simplemente revise los índices:
Ir a través de índices + variable de índice:
Control de conteo de bucle + índice variable:
fuente
Había estado tratando de construir un menú (en Camping y Markaby ) usando un hash.
Cada elemento tiene 2 elementos: una etiqueta de menú y una URL , por lo que un hash parecía correcto, pero la URL '/' para 'Inicio' siempre aparecía en último lugar (como era de esperar para un hash), por lo que los elementos de menú aparecían incorrectos orden.
Usar una matriz con
each_slice
hace el trabajo:Agregar valores adicionales para cada elemento del menú (por ejemplo, como un nombre de ID de CSS ) solo significa aumentar el valor del segmento. Entonces, como un hash pero con grupos que consisten en cualquier número de elementos. Perfecto.
¡Esto es solo para decir gracias por insinuar inadvertidamente una solución!
Obvio, pero vale la pena declarar: sugiero verificar si la longitud de la matriz es divisible por el valor de corte.
fuente
Si usa el mixin enumerable (como lo hace Rails), puede hacer algo similar al fragmento de php enumerado. Solo usa el método each_slice y aplana el hash.
Se requieren menos parches de mono.
Sin embargo, esto causa problemas cuando tiene una matriz recursiva o un hash con valores de matriz. En ruby 1.9, este problema se resuelve con un parámetro para el método de aplanamiento que especifica qué tan profundo debe repetirse.
En cuanto a la pregunta de si esto es un olor a código, no estoy seguro. Por lo general, cuando tengo que inclinarme hacia atrás para iterar sobre algo, retrocedo y me doy cuenta de que estoy atacando mal el problema.
fuente
La forma correcta es aquella con la que se siente más cómodo y que hace lo que quiere que haga. En la programación rara vez hay una forma "correcta" de hacer las cosas, más a menudo hay varias formas de elegir.
Si se siente cómodo con cierta forma de hacer las cosas, hágalo, a menos que no funcione, entonces es hora de encontrar una mejor manera.
fuente
En Ruby 2.1, se elimina cada método index_with_index. En su lugar, puede usar each_index
Ejemplo:
produce:
fuente
each_with_index
que no aparece en la documentación es porque lo proporciona elEnumerable
módulo.Usar el mismo método para iterar a través de matrices y hash tiene sentido, por ejemplo, para procesar estructuras de hash y matrices anidadas que a menudo resultan de analizadores, de leer archivos JSON, etc.
Una forma inteligente que aún no se ha mencionado es cómo se hace en la biblioteca Ruby Facets de extensiones de biblioteca estándar. Desde aquí :
Ya hay
Hash#each_pair
un alias deHash#each
. Entonces, después de este parche, también lo tenemosArray#each_pair
y podemos usar indistintamente para iterar a través de Hashes y Arrays. Esto corrige la locura observada del OP queArray#each_with_index
tiene los argumentos de bloque invertidos en comparación conHash#each
. Ejemplo de uso:fuente