Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between << and +=?

Tags:

arrays

ruby

I have been playing around with arrays a bit, and found myself in trouble understanding the following code:

first_array = []
second_array = []
third_array = []                         # I initialized 3 empty arrays

third_array << [1,2,3,4,5,6,7,8,9]       # I loaded 1..9 into third_array[0]
puts third_array.size                    # => 1

first_array << third_array               # 1..9 was loaded into first_array[0]

second_array += third_array              # 1..9 was loaded into second_array[0]

puts first_array == third_array          # false
puts second_array == third_array         # true
puts first_array == second_array         # false

puts first_array.size                    # 1
puts second_array.size                   # 1
puts third_array.size                    # 1

What happened with this?

second_array += third_array              # I have no clue

Why aren't all the arrays equal to each other?

like image 792
swbergmann Avatar asked May 07 '13 20:05

swbergmann


2 Answers

They exhibit fairly different behaviors. One creates and assigns a new Array object, the other modifies an existing object.

+= would be the same as second_array = second_array + third_array. This sends the + message to the second_array object passing third_array as the argument.

Per the documentation Array.+ returns a new array object built by concatenating the two arrays. This will return a new object.

Array.<< simply push the parameter to the end of the existing array object:

second_array = []
second_array.object_id = 1234

second_array += [1,2,3,4]
second_array.object_id = 5678

second_array << 5
second_array.object_id = 5678

There is also a difference in how the parameter is added. By adding other elements, it will help see why your arrays are not equal:

second_array = [1, 2, 3]

# This will push the entire object, in this case an array
second_array << [1,2]
# => [1, 2, 3, [1,2]]

# Specifically appends the individual elements,
# not the entire array object
second_array + [4, 5]
# => [1, 2, 3, [1,2], 4, 5]

This is because Array.+ uses concatenation instead of pushing. Unlike Array.concat which modifies the existing object, Array.+ returns a new object.

You can think of a Ruby implementation like:

class Array
  def +(other_arr)
    dup.concat(other_arr)
  end
end

In your specific example, your objects look like this at the end:

first_array  = [[[1, 2, 3, 4, 5, 6, 7, 8, 9]]] # [] << [] << (1..9).to_a
second_array =  [[1, 2, 3, 4, 5, 6, 7, 8, 9]]  # [] + ([] << (1..9).to_a)
third_array  =  [[1, 2, 3, 4, 5, 6, 7, 8, 9]]  # [] << (1..9).to_a
like image 106
Aaron K Avatar answered Nov 04 '22 17:11

Aaron K


<< appends an item to an array

+= adds an array to an array.

Examples:

[1,2] << 3 # returns [1,2,3]

[1,2] += [3,4] # returns [1,2,3,4]

like image 45
Teddy Avatar answered Nov 04 '22 16:11

Teddy