简体   繁体   中英

What is the difference between << and +=?

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?

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

<< 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]

The last difference not mentioned so far between << and += is, that << is a method:

class Array
  def << other
    # performs self.push( other )
  end
end

whereas += is syntax:

a += b

and is merely a shorthand for writing:

a = a + b

So, in order to modify += behavior, one has to modify the + method:

class Array
  def + other
    # ....
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM