Comment modifier un tableau pendant que je l'itère dans Ruby?

88

J'apprends juste Ruby, alors je m'excuse si c'est trop débutant pour ici, mais je ne peux pas comprendre cela à partir du livre de pioche (probablement juste de ne pas lire assez attentivement). Quoi qu'il en soit, si j'ai un tableau comme celui-ci:

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

... et je veux, disons, multiplier chaque valeur du tableau par 3, j'ai calculé cela en faisant ce qui suit:

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

... ne m'obtiendra pas ce que je veux (et je comprends pourquoi, je ne modifie pas le tableau lui-même).

Ce que je n'obtiens pas, c'est comment modifier le tableau d'origine à l'intérieur du bloc de code après l'itérateur. Je suis sûr que c'est très facile.

Brad
la source

Réponses:

140

Utilisez mappour créer un nouveau tableau à partir de l'ancien:

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

Utilisez map!pour modifier le tableau en place:

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

Regardez-le fonctionner en ligne: ideone

Mark Byers
la source
2
Si vous avez vraiment besoin de modifier chaque élément, l'utilisation de la carte serait certainement plus élégante, à mon humble avis.
fresskoma
2
Et si vous souhaitez modifier le tableau lui-même, utilisez map! à la place
Yoann Le Touche
18

Pour modifier directement le tableau, utilisez arr.map! {|item| item*3}. Pour créer un nouveau tableau basé sur l'original (ce qui est souvent préférable), utilisez arr.map {|item| item*3}. En fait, je réfléchis toujours à deux fois avant d'utiliser each, car il y a généralement une fonction d'ordre supérieur comme map, selectou injectqui fait ce que je veux.

Mandrin
la source
Que faire si vous ne souhaitez pas effectuer d'opération d'énumération? Et si vous voulez simplement faire quelque chose comme arr.map!{ destructive_op}changer de façon permanente arr?
étoile brillante
1
@TrevorAlexander: Je ne suis pas sûr de ce que tu veux dire. Cela pourrait valoir la peine de poser une vraie question avec des détails et des trucs.
Chuck
Je vais devoir y réfléchir. À part la modification d'éléments très étroits, quelles opérations destructives sur les structures ne sont pas énumérables?
étoile brillante
@TrevorAlexander: J'ai encore du mal à comprendre. Si vous ne pouvez pas regarder le contenu d'une structure, vous ne pouvez pas transformer son contenu. On dirait que vous n'êtes pas intéressé par la modification d'une structure, mais que vous voulez simplement attribuer une variable - mais je me trompe peut-être.
Chuck
5
arr.collect! {|item| item * 3}
Jeff Richardson
la source