Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 294
HectorOfTroy407 Avatar asked Feb 13 '26 05:02

HectorOfTroy407


2 Answers

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.

like image 175
spickermann Avatar answered Feb 15 '26 23:02

spickermann


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.

like image 34
7stud Avatar answered Feb 15 '26 22:02

7stud



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!