¿Cómo modifico una matriz mientras la estoy iterando en Ruby?

88

Estoy aprendiendo a Ruby, así que me disculpo si esto es demasiado novato por aquí, pero no puedo resolver esto con el libro de la piqueta (probablemente no estoy leyendo con suficiente atención). De todos modos, si tengo una matriz como esta:

arr = [1,2,3,4,5]

... y quiero, digamos, multiplicar cada valor en la matriz por 3, lo he resuelto haciendo lo siguiente:

arr.each {|item| item *= 3}

... no me dará lo que quiero (y entiendo por qué, no estoy modificando la matriz en sí).

Lo que no entiendo es cómo modificar la matriz original desde el interior del bloque de código después del iterador. Seguro que es muy fácil.

puntilla
fuente

Respuestas:

140

Úselo mappara crear una nueva matriz a partir de la anterior:

arr2 = arr.map {|item| item * 3}

Úselo map!para modificar la matriz en su lugar:

arr.map! {|item| item * 3}

Véalo funcionando en línea: ideone

Mark Byers
fuente
2
Si realmente necesita modificar cada elemento, usar map definitivamente sería más elegante, en mi humilde opinión.
fresskoma
2
¡Y si desea modificar la matriz, use map! en su lugar
Yoann Le Touche
18

Para modificar directamente la matriz, use arr.map! {|item| item*3}. Para crear una nueva matriz basada en la original (que a menudo es preferible), use arr.map {|item| item*3}. De hecho, siempre lo pienso dos veces antes de usar each, porque generalmente hay una función de orden superior como map, selecto injectque hace lo que quiero.

Arrojar
fuente
¿Qué sucede si no desea realizar una operación de enumeración? ¿Qué pasa si solo quieres hacer algo comoarr.map!{ destructive_op} cambiar permanentemente arr?
estrella brillante
1
@TrevorAlexander: No estoy seguro de lo que quieres decir. Podría valer la pena hacer una pregunta real con detalles y demás.
Chuck
Tendré que pensar sobre eso. Aparte de la modificación de elementos muy estrechos, ¿qué operaciones destructivas en estructuras no son enumerables?
estrella brillante
@TrevorAlexander: Todavía me cuesta entender. Si no puede mirar el contenido de una estructura, no puede transformar su contenido. Parece que no estás interesado en modificar una estructura y, en su lugar, solo quieres asignar una variable, pero podría estar malinterpretado.
Chuck
5
arr.collect! {|item| item * 3}
Jeff Richardson
fuente