Ruby + 和数组的 concat 有什么区别?

What the difference between Ruby + and concat for arrays?

我一直在尝试将包含数字的数组收集到一个数组中。如果我尝试使用 + it returns 空数组作为输出。使用 concat returns 预期的数字数组。它是如何工作的,这些 Ruby 方法之间的主要区别是什么?

0.step.with_object([]) do |index, output|
  output + [index]
  break output if index == 100
do # returns empty array

0.step.with_object([]) do |index, output|
  output.concat [index]
  break output if index == 100
end # returns an array contains digits from 0 to 100

不同于Enumerable#reduce, Enumerable#each_with_object通过还原过程传递相同的对象。

Array#+ 创建一个 新实例 ,保持原始对象不变。
Array#concat 突变 原始对象。

reduce结果相同:

0.step.reduce([]) do |acc, index|
  break acc if index > 100
  acc + [index]
end

让我们创建两个数组:

a = [1, 2]
b = [3, 4]

与所有对象一样,这些数组具有唯一的对象 ID:

a.object_id  #=> 48242540181360 
b.object_id  #=> 48242540299680 

现在让我们将它们加在一起:

c = a + b    #=> [1, 2, 3, 4] 

这将创建一个新对象(由变量 c 保存):

c.object_id  #=> 48242540315060 

并保持 ab(以及它们的对象 ID)不变:

a            #=> [1, 2] 
b            #=> [3, 4]

现在,让我们写:

a += b       #=> [1, 2, 3, 4]

其中 Ruby 更改为:

a = a + b

编译代码时。我们得到:

a            #=> [1, 2, 3, 4] 
a.object_id  #=> 48242541482040

变量 a 现在包含一个新对象,该对象等于 a 的先前值加上 b

现在让我们将 ba 的(新值)连接起来:

a.concat(b)  #=> [1, 2, 3, 4, 3, 4]  

这会改变 (mutates) a,但当然不会改变 a 的对象 id:

a            #=> [1, 2, 3, 4, 3, 4] 
a.object_id  #=> 48242541482040  

最后,我们可以将 a 的值替换为 c,而不影响 a 的对象 ID:

a.replace(c) #=> [1, 2, 3, 4]
a            #=> [1, 2, 3, 4] 
a.object_id  #=> 48242541482040

参见 Array#+, Array#concat and Array#replace