将数组推入另一个数组中作为值

时间:2014-08-13 02:18:37

标签: ruby arrays immutability

如何将数组作为值附加到另一个数组中而不作为引用?下面举例说明:

a = []
m = []
i = 1

# first loop
a[0] = i      
a[1] = i + 1
m << a #=> [[1,2]]

i += 1

# second loop
a[0] = i
a[1] = i + 1
m << a #=> [[2,3],[2,3]]

我期待[[1,2],[2,3]]之类的内容。

4 个答案:

答案 0 :(得分:2)

将第一个m << a替换为m << a.dup。这会将dup的副本(或a许可)推送到m,这与a不同,因此当您修改a时,您赢了&#39} ;修改m中的对象。一种看待这种情况的方法如下:

a = []
m = []
m << a
a << 0
m #=> [[0]]

x = a.dup 
m << x
m #=> [[0], [0]]

a << 1
m #=> [[0, 1], [0]]

x << 2
m #=> [[0, 1], [0, 2]]

答案 1 :(得分:2)

您可以通过检查各种对象的ID来更好地了解这里发生了什么。

a = []
a.object_id    #=> 2164985760
m = []
i = 1

第一次循环

a[0] = i       #=> 1      
a[1] = i + 1   #=> 2
a.object_id    #=> 2164985760
m << a         #=> [[1,2]]
m.object_id    #=> 2165031720
m[0].object_id #=> 2164985760

第二次循环

i += 1
a[0] = i       #=> 2
a[1] = i + 1   #=> 3
a.object_id    #=> 2164985760
m << a         #=> [[2, 3], [2, 3]]
m.object_id    #=> 2165031720
m[0].object_id #=> 2164985760
m[1].object_id #=> 2164985760

现在让我们再试一次,只需一次更改。正如@sawa建议的那样,在第二个循环之前添加a = []。 (以下对象ID当然会与上面的不同。)

a = []
a.object_id     #=> 2164690760
m = []
i = 1

第一次循环

a[0] = i       #=> 1
a[1] = i + 1   #=> 2
a.object_id    #=> 2164690760
m << a         #=> [[1, 2]]
m.object_id    #=> 2164655180
m[0].object_id #=> 2164690760

第二次循环

a = []
a.object_id    #=> 2161060600
i += 1         #=> 2
a[0] = i       #=> 2
a[1] = i + 1   #=> 3
a.object_id    #=> 2161060600
m << a         #=> [[1, 2], [2, 3]]
m.object_id    #=> 2164655180
m[0].object_id #=> 2164690760
m[1].object_id #=> 2161060600

答案 2 :(得分:1)

a分配给另一个阵列。

m = []

i = 1
a = []
a[0] = i      
a[1] = i + 1
m << a

i += 1
a = []
a[0] = i
a[1] = i + 1
m << a

答案 3 :(得分:0)

如果您在循环后期望得到类似[[1,2],[2,3]]的内容,那么您可能应该使用.map的Ruby功能来循环并返回一个数组。

这样你就不用担心管理中间变量(甚至是你的例子中的计数器):

loop_count = 2 # or whatever currently determines how many loops you make
m = (1..loop_count).map do |i|
  [i, i+1]
end

m #=> [[1,2],[2,3]]