对于凌乱的标题感到抱歉。
如果我使用静态值(rails console):
2.1.2 :013 > h=[]
=> []
2.1.2 :014 > h<<[1]
=> [[1]]
2.1.2 :015 > h<<[1,2]
=> [[1], [1, 2]]
2.1.2 :016 > h<<[1,2,3]
=> [[1], [1, 2], [1, 2, 3]]
它按预期工作。如果我使用一个使用静态值的变量,就像这样:
2.1.2 :018 > h=[]
=> []
2.1.2 :019 > a=1
=> 1
2.1.2 :020 > h<<a
=> [1]
2.1.2 :021 > a=[1,2]
=> [1, 2]
2.1.2 :022 > h<<a
=> [1, [1, 2]]
2.1.2 :023 > a=[1,2,3]
=> [1, 2, 3]
2.1.2 :024 > h<<a
=> [1, [1, 2], [1, 2, 3]]
但如果我执行以下操作,则变量的值将替换为整个数组,就像它是一个指针一样:
2.1.2 :036 > h=[]
=> []
2.1.2 :037 > a=[]
=> []
2.1.2 :038 > a<<1
=> [1]
2.1.2 :039 > h<<a
=> [[1]]
2.1.2 :040 > a<<2
=> [1, 2]
2.1.2 :041 > h<<a
=> [[1, 2], [1, 2]]
2.1.2 :042 > a<<3
=> [1, 2, 3]
2.1.2 :043 > h<<a
=> [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
注意h的所有值如何被a的新值替换。如果我使用&#34; h.append(X)&#34;则会发生同样的情况。如果我使用其他变量,则值不会被替换:
2.1.2 :044 > b=[1,2,3]
=> [1, 2, 3]
2.1.2 :045 > b<<4
=> [1, 2, 3, 4]
2.1.2 :046 > h<<b
=> [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3, 4]]
我通过使用&#34; h&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; a.to_s&#34;,但是将数值转换为字符串,当我需要对它们进行数学运算时会导致问题。我遇到的另一种选择是使用&#34; h&lt;&lt; a.inspect&#34;,除了这些值被这样的引号所包围:
["[1]", "[1,2]", "[1,2,3]"]
这是好的,但引号也引起了其他问题。理想情况下,我希望他们这样:
[[1], [1,2], [1,2,3]]
有没有办法防止这种情况发生?或者,使用不同的方法将数组插入到散列/数组/ json变量中?
答案 0 :(得分:3)
您可以在插入数组之前复制引用:
> h = []
> a = []
> a << 1
> h << a.dup
> a << 2
> h << a.dup
> a << 3
> h << a.dup
> h
# => [[1], [1, 2], [1, 2, 3]]
答案 1 :(得分:2)
您需要了解Ruby有效地通过引用传递参数 ¹ - 只有基本类型(如float,int,true,false和nil)是不可变的,因此不会暴露您观察到的行为。对于所有其他对象,一种可能的解决方法是使用dup
:
h = []
a = []
a = a.dup << 1 #=> [1]
h << a #=> [[1]]
a = a.dup << 2 #=> [1, 2]
h << a #=> [[1], [1, 2]]
a = a.dup << 3 #=> [1, 2, 3]
h << a #=> [[1], [1, 2], [1, 2, 3]]
h #=> [[1], [1, 2], [1, 2, 3]]
另一种方法是使用+=
隐式返回副本。但是,右手参数必须是数组而不是单个值:
h = []
a = []
a += [1] #=> [1]
h << a #=> [[1]]
a += [2] #=> [1, 2]
h << a #=> [[1], [1, 2]]
a += [3] #=> [1, 2, 3]
h << a #=> [[1], [1, 2], [1, 2, 3]]
h #=> [[1], [1, 2], [1, 2, 3]]
¹虽然在内部,Ruby通过值传递它们,但这些值是引用
答案 2 :(得分:0)
您可以获取变量&#39; a&#39;的对象ID通过Object#object_id,它可以帮助您理解。
irb(main):060:0> a= 1
=> 1
irb(main):061:0> a.object_id
=> 3
irb(main):062:0> a= [1,2]
=> [1, 2]
irb(main):063:0> a.object_id
=> 20017440
irb(main):064:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):065:0> a.object_id
=> 19627820
变量a的object_id不同。
irb(main):066:0> a= []
=> []
irb(main):067:0> a << 1
=> [1]
irb(main):068:0> a.object_id
=> 18718920
irb(main):069:0> a << 2
=> [1, 2]
irb(main):070:0> a.object_id
=> 18718920
irb(main):071:0> a << 3
=> [1, 2, 3]
irb(main):072:0> a.object_id
=> 18718920
如果您使用&#34;&lt;&lt;&#;&#34;,变量&#39; a&#39;的object_id不会改变,如果你改变变量a的值,那么数组的所有元素都会被改变。会改变。
所以你可以使用&#39; a.dup&#39;获取对象a的浅表副本,然后将其添加到数组h。