Como modifico um array enquanto estou iterando sobre ele no Ruby?

88

Estou apenas aprendendo Ruby, então me desculpe se isso for muito novo por aqui, mas não consigo resolver isso no livro de picaretas (provavelmente não estou lendo com cuidado o suficiente). De qualquer forma, se eu tiver uma matriz como esta:

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

... e eu quero, digamos, multiplicar cada valor na matriz por 3, eu trabalhei fazendo o seguinte:

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

... não vai me dar o que eu quero (e eu entendo porque, não estou modificando o array em si).

O que eu não entendo é como modificar a matriz original de dentro do bloco de código após o iterador. Tenho certeza de que isso é muito fácil.

brad
fonte

Respostas:

140

Use mappara criar uma nova matriz a partir da antiga:

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

Use map!para modificar a matriz no local:

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

Veja funcionando online: ideone

Mark Byers
fonte
2
Se você realmente precisa modificar cada elemento, usar o mapa seria definitivamente mais elegante, imho.
fresskoma
2
E se você quiser modificar o próprio array, use map! em vez disso
Yoann Le Touche
18

Para modificar diretamente a matriz, use arr.map! {|item| item*3}. Para criar um novo array baseado no original (o que geralmente é preferível), use arr.map {|item| item*3}. Na verdade, sempre penso duas vezes antes de usar each, porque geralmente há uma função de ordem superior como map, selectou injectfaz o que eu quero.

Mandril
fonte
E se você não quiser fazer uma operação de enumeração? E se você apenas quiser fazer algo como arr.map!{ destructive_op}mudar permanentemente arr?
estrela brilhante de
1
@TrevorAlexander: Não tenho certeza do que você quer dizer. Pode valer a pena fazer uma pergunta real com detalhes e outras coisas.
Chuck
Vou ter que pensar sobre isso. Além da modificação de elemento muito restrita, quais operações destrutivas em estruturas não são enumeráveis?
estrela brilhante de
@TrevorAlexander: Ainda estou tendo dificuldade em entender. Se você não pode olhar o conteúdo de uma estrutura, não pode transformar seu conteúdo. Parece que você não está interessado em modificar uma estrutura e, em vez disso, deseja apenas atribuir uma variável - mas posso estar enganado.
Chuck
5
arr.collect! {|item| item * 3}
Jeff Richardson
fonte