96

I'm just learning Ruby so apologies if this is too newbie for around here, but I can't work this out from the pickaxe book (probably just not reading carefully enough). Anyway, if I have an array like so:

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

...and I want to, say, multiply each value in the array by 3, I have worked out that doing the following:

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

...will not get me what I want (and I understand why, I'm not modifying the array itself).

What I don't get is how to modify the original array from inside the code block after the iterator. I'm sure this is very easy.

0

4 Answers 4

156

Use map to create a new array from the old one:

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

Use map! to modify the array in place:

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

See it working online: ideone

Sign up to request clarification or add additional context in comments.

2 Comments

If you really need to modify each element, using map would definitely be more elegant, imho.
And if you want to modify the array itself use map! instead
21

To directly modify the array, use arr.map! {|item| item*3}. To create a new array based on the original (which is often preferable), use arr.map {|item| item*3}. In fact, I always think twice before using each, because usually there's a higher-order function like map, select or inject that does what I want.

4 Comments

What if you don't want to do an enumerating operation? What if you just want to do something like arr.map!{ destructive_op} to permanently change arr?
@TrevorAlexander: I'm not sure what you mean. It might be worth asking as a real question with details and stuff.
I'll have to think about it. Other than very narrow element modification, what destructive operations on structures aren't enumerable?
@TrevorAlexander: I am still having a hard time understanding. If you can't look at a structure's contents, you can't transform its contents. It kind of sounds like you aren't interested in modifying a structure, and instead just want to assign a variable — but I might be misunderstanding.
5
arr.collect! {|item| item * 3} 

Comments

-1

Others have already mentioned that array.map is the more elegant solution here, but you can simply add a "!" to the end of array.each and you can still modify the array. Adding "!" to the end of #map, #each, #collect, etc. will modify the existing array.

2 Comments

Tried this, but for both each! and each_with_index! I get an undefined method error
This is wrong, as there's no built-in method in Ruby's like each! and/or each_with_index!. I'd recommend to double check your answer, Andrew. This applies to some methods only (map!, compact!, collect!, reject!, etc).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.