HectorOfTroy407
HectorOfTroy407

Reputation: 1917

Modify an Array in Place - Ruby

I'm wondering why the following will not modify the array in place.

I have this:

@card.map!.with_index {|value, key|  key.even? ? value*=2 : value}

Which just iterates over an array, and doubles the values for all even keys.

Then I do:

@card.join.split('').map!{|x| x.to_i}

Which joins the array into one huge number, splits them into individual numbers and then maps them back to integers in an array. The only real change from step one to step two is step one would look like a=[1,2,12] and step two would look like a=[1,2,1,2]. For the second step, even though I use .map! when I p @card it appears the exact same after the first step. I have to set the second step = to something if I want to move onward with they new array. Why is this? Does the .map! in the second step not modify the array in place? Or do the linking of methods negate my ability to do that? Cheers.

Upvotes: 3

Views: 4189

Answers (2)

spickermann
spickermann

Reputation: 107107

tldr: A method chain only modifies objects in place, if every single method in that chain is a modify-in-place method.

The important difference in the case is the first method you call on your object. Your first example calls map! that this a methods that modifies the array in place. with_index is not important in this example, it just changes the behavior of the map!.

Your second example calls join on your array. join does not change the array in place, but it returns a totally different object: A string. Then you split the string, which creates a new array and the following map! modifies the new array in place.

So in your second example you need to assign the result to your variable again:

@card = @card.join.split('').map{ |x| x.to_i }

There might be other ways to calculate the desired result. But since you did not provide input and output examples, it is unclear what you're trying to achieve.

Upvotes: 2

7stud
7stud

Reputation: 48649

Does the .map! in the second step not modify the array in place?

Yes, it does, however the array it modifies is not @card. The split() method returns a new array, i.e. one that is not @card, and map! modifies the new array in place.

Check this out:

tap{|x|...} → x
Yields [the receiver] to the block, and then returns [the receiver]. 
The primary purpose of this method is to “tap into” a method chain, 
in order to perform operations on intermediate results within the chain.  

@card = ['a', 'b', 'c']
puts @card.object_id

@card.join.split('').tap{|arr| puts arr.object_id}.map{ |x| x.to_i }  #arr is whatever split() returns

--output:--
2156361580
2156361380

Every object in a ruby program has a unique object_id.

Upvotes: 2

Related Questions