Jak zmodyfikować tablicę podczas iteracji po niej w Rubim?

88

Po prostu uczę się Rubiego, więc przepraszam, jeśli to jest zbyt nowicjusz na to tutaj, ale nie mogę tego rozwiązać z książki o kilofie (prawdopodobnie po prostu nie czytam wystarczająco uważnie). W każdym razie, jeśli mam taką tablicę:

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

... i chcę, powiedzmy, pomnożyć każdą wartość w tablicy przez 3, wypracowałem to, wykonując następujące czynności:

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

... nie da mi tego, czego chcę (i rozumiem dlaczego, nie modyfikuję samej tablicy).

Nie rozumiem, jak zmodyfikować oryginalną tablicę z wnętrza bloku kodu po iteratorze. Jestem pewien, że to bardzo proste.

ćwiek
źródło

Odpowiedzi:

140

Użyj, mapaby utworzyć nową tablicę ze starej:

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

Służy map!do modyfikowania tablicy w miejscu:

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

Zobacz, jak działa online: ideone

Mark Byers
źródło
2
Jeśli naprawdę potrzebujesz zmodyfikować każdy element, użycie mapy byłoby zdecydowanie bardziej eleganckie, imho.
fresskoma
2
A jeśli chcesz zmodyfikować samą tablicę, użyj map! zamiast tego
Yoann Le Touche
18

Aby bezpośrednio zmodyfikować tablicę, użyj arr.map! {|item| item*3}. Aby utworzyć nową tablicę na podstawie oryginału (co jest często preferowane), użyj arr.map {|item| item*3}. W rzeczywistości zawsze dwa razy się zastanawiam przed użyciem each, ponieważ zwykle istnieje funkcja wyższego rzędu map, selectlub injectrobi to, co chcę.

Gdakanie
źródło
A jeśli nie chcesz wykonywać operacji wyliczania? A co, jeśli chcesz po prostu zrobić coś takiego, jak arr.map!{ destructive_op}trwale zmienić arr?
jasna gwiazda
1
@TrevorAlexander: Nie jestem pewien, co masz na myśli. Może warto zadać prawdziwe pytanie ze szczegółami i rzeczami.
Chuck
Muszę o tym pomyśleć. Oprócz bardzo wąskiej modyfikacji elementów, jakich destrukcyjnych operacji na strukturach nie da się wyliczyć?
jasna gwiazda
@TrevorAlexander: Nadal mam problemy ze zrozumieniem. Jeśli nie możesz spojrzeć na zawartość struktury, nie możesz przekształcić jej zawartości. Wygląda na to, że nie jesteś zainteresowany modyfikowaniem struktury, a zamiast tego chcesz po prostu przypisać zmienną - ale mogę być nieporozumieniem.
Chuck
5
arr.collect! {|item| item * 3}
Jeff Richardson
źródło