Daniel Holly
Daniel Holly

Reputation: 61

ruby shift - how to shift an array without shifting an array that it was assigned to

I assign one array to another:

a = ['who','let','the','dogs','out']
b = a
b.shift

b and a now both are

["let", "the", "dogs", "out"].

I would like for a to still be

["who","let", "the", "dogs", "out"]

How can you mutate b without mutating a?

Also, why does this happen?

Thanks!

Upvotes: 2

Views: 816

Answers (2)

Jeff Price
Jeff Price

Reputation: 3229

When you say:

b = a

You are saying let b point to the same object as a. You are not saying copy the contents of a into b. For that you would need to use the method clone. In addition to guitarman's answer, there is an array method that will return the rest of the array after shifting without changing the original array. This only works if you don't care what you are shifting/dropping off the array and are only concerned about the remaining items.

1 > a = ['who','let','the','dogs','out']
 => ["who", "let", "the", "dogs", "out"] 
2 > b = a.drop(1)
 => ["let", "the", "dogs", "out"] 
3 > a
 => ["who", "let", "the", "dogs", "out"] 
4 > b
 => ["let", "the", "dogs", "out"] 

Upvotes: 1

guitarman
guitarman

Reputation: 3310

That's because b and a references to the same object in the memory:

a = ['who','let','the','dogs','out']
b = a
a.object_id == b.object_id
# => true

b needs to be another array object, so I would create a clone of a:

a = ['who','let','the','dogs','out']
b = a.dup
a.object_id == b.object_id
# => false

b.shift
# => "who"
b
# => ["let", "the", "dogs", "out"]
a
# => ["who", "let", "the", "dogs", "out"]

Upvotes: 7

Related Questions