Як я можу змінити масив під час ітерації над ним у Ruby?


88

Я просто вивчаю Рубі, тому вибачаюся, якщо це занадто новачок для цього, але я не можу це зрозуміти з книги про кирку (можливо, просто недостатньо уважно читаю). У всякому разі, якщо у мене є такий масив:

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

... і я хочу, скажімо, помножити кожне значення в масиві на 3, я розробив це, роблячи наступне:

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

... не отримає мені те, що я хочу (і я розумію, чому, я не змінюю сам масив).

Я не отримую, як змінити оригінальний масив зсередини блоку коду після ітератора. Я впевнений, що це дуже просто.

Відповіді:


140

Використовуйте mapдля створення нового масиву зі старого:

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

Використовуйте map!для зміни масиву на місці:

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

Подивіться, як це працює в Інтернеті: ideone


2
Якщо вам дійсно потрібно змінити кожен елемент, використання карти, безумовно, було б більш елегантним, imho.
fresskoma

2
А якщо ви хочете змінити сам масив, використовуйте map! натомість
Йоанн Ле Туш

18

Щоб безпосередньо змінити масив, використовуйте arr.map! {|item| item*3}. Щоб створити новий масив на основі оригіналу (що часто є кращим), використовуйте arr.map {|item| item*3}. Насправді, я завжди двічі замислююся перед використанням each, тому що зазвичай існує функція вищого порядку, наприклад map, selectабо injectвона робить те, що я хочу.


Що робити, якщо ви не хочете робити операцію перерахування? Що робити, якщо ви просто хочете зробити щось на зразок arr.map!{ destructive_op}постійних змін arr?
яскрава зірка

1
@TrevorAlexander: Я не впевнений, що ти маєш на увазі. Можливо, варто поставити справжнє запитання з деталями та іншим.
Чак

Мені доведеться про це подумати. Окрім дуже вузької модифікації елементів, яких руйнівних операцій на конструкціях не можна перерахувати?
яскрава зірка

@TrevorAlexander: Мені все ще важко зрозуміти. Якщо ви не можете розглянути вміст структури, ви не можете перетворити її вміст. Це начебто звучить так, що ви не зацікавлені в зміні структури, а натомість просто хочете призначити змінну - але, можливо, я не розумію.
Чак

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.