2013-05-07 6 views
6

Я играл вокруг с массивами немного, и оказался в беде понимание следующий код:В чем разница между << и + =?

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 

Что случилось с этим?

second_array += third_array    # I have no clue 

Почему не все массивы равны друг другу?

ответ

7

Они демонстрируют довольно различное поведение. Один создает и назначает новый объект Array, другой изменяет существующий объект.

+= будет таким же, как second_array = second_array + third_array. Это отправляет сообщение + объекту second_array, передающему third_array в качестве аргумента.

В документации Array.+ возвращается новый объект массива, построенный путем объединения двух массивов. Это вернет новый объект.

Array.<< просто нажать параметр в конец существующего массива объектов:

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 

Существует также разница в том, как добавляется параметр. При добавлении других элементов, это поможет понять, почему ваши массивы не равны:

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] 

Это потому, что Array.+ использует конкатенацию вместо нажатия. В отличие от Array.concat, который изменяет существующий объект, Array.+ возвращает новый объект.

Вы можете думать о реализации Ruby, как:

class Array 
    def +(other_arr) 
    dup.concat(other_arr) 
    end 
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 
+2

Так вашу точку что для second_array создается новый массив, который не равен третьему, даже если содержимое двух массивов одинаково? – nzs

+0

THAT @codedad до сих пор не ответил! кто-нибудь понимает это? – rubybrah

+0

second_array выполняет равенство третьего_аррея (но он создал новый объект), это показывает исходный пример. first_array не равно ни –

3

<< добавляет элемент в массив

+= добавляет массив к массиву.

Примеры:

[1,2] << 3 # возвращает [1,2,3]

[1,2] += [3,4] # возвращает [1,2,3,4]

+6

Ваш пример для '<<' был бы лучше, если бы вы показали, что '[1,2] << [3,4]' производится '[1,2, [3,4]]' IMHO. – squiguy

+0

@squiguy вы правы. и Тедди. Вы имеете в виду, что в моем примере first_array = [1,2,3,4,5,6,7,8,9] и second_array = [[1,2,3,4,5,6,7, 8,9]]? это верно? – rubybrah

+1

@rubybrah no. 'third_array' is' [[1..9]] ',' first_array' is '[[[1..9]]]' и 'second_array' is' [[1..9]] ' –

3

Последнее различие не упоминается так далеко друг от друга и <<+= в том, что << представляет собой метод:

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

тогда += является Синтаксис:

a += b 

и просто сокращенная для записи:

a = a + b 

Таким образом, для того, чтобы изменить += поведение, необходимо изменить + метод:

class Array 
    def + other 
    # .... 
    end 
end 
Смежные вопросы