[英]Array/Hash strange behaviour
I have performed the following test: 我已经执行了以下测试:
irb(main):023:0> a=[]
=> []
irb(main):024:0> b="1"
=> "1"
irb(main):025:0> a.push(b)
=> ["1"]
irb(main):026:0> a
=> ["1"]
irb(main):027:0> b="2"
=> "2"
irb(main):028:0> a
=> ["1"]
So far so good. 到现在为止还挺好。 Now, but as soon as I change b into a hash: 现在,但是一旦我将b更改为哈希:
irb(main):012:0> a=[]
=> []
irb(main):013:0> b={}
=> {}
irb(main):014:0> b[:file]="one"
=> "one"
irb(main):015:0> a.push(b)
=> [{:file=>"one"}]
irb(main):016:0> a
=> [{:file=>"one"}]
irb(main):017:0> b[:file]="two"
=> "two"
irb(main):018:0> a
**=> [{:file=>"two"}]**
I didn't even push the b value into the a array. 我什至没有将b值推送到a数组中。 What happened here? 这里发生了什么?
b
is not a hash. b
不是哈希。 It is a reference to a hash. 它是对哈希的引用 。 And pushing a reference somewhere else won't make it point to a new instance. 并且将引用推送到其他位置不会使其指向新实例。
Copy your hashes explicitly where you want to, using b.dup
. 使用b.dup
将哈希明确复制到想要的b.dup
。
Sometimes even that might not be enough, as the same applies to values inside a hash: the new hash will have the same references inside, it's a so-called "shallow copy" . 有时甚至还不够,因为对于哈希内的值也是如此:新哈希在内部具有相同的引用,这就是所谓的“浅表副本” 。
(Here I was claiming that strings are immutable in Ruby, but @BroiSatse pointed out that it's not true, and he's right, follow the link in the comments.) (在这里我声称字符串在Ruby中是不可变的,但是@BroiSatse指出这是不正确的,他是对的,请按照注释中的链接进行操作。)
Regardless, the explaination is similar: assignment of a new string into a variable produces a new reference to a string (doesn't mutate existing one), writing a new value into a hash doesn't produce a new hash reference (mutates existing hash instead). 无论如何,解释是相似的: 将新字符串分配给变量会产生对字符串的新引用 (不会改变现有的哈希值 ), 将新值写入哈希不会产生新的哈希引用(会使现有哈希值突变)代替)。
You need to understand how ruby variables and Arrays works. 您需要了解ruby变量和数组的工作方式。 Variable holds a reference to the object, which means that if you do: 变量保存对对象的引用,这意味着如果执行以下操作:
a = b = []
Both a
and b
are referencing exactly some object! a
和b
都完全引用了某个对象!
a << 1
b #=> [1]
Array is nothing else but an object which holds many references at the same time. 数组不过是一个对象,它同时拥有许多引用。 But again, they just reference objects, so if you do: 但同样,它们只是引用对象,所以如果您这样做:
a = {}
b = [a]
Then b[0]
and a
variable are referencing to the same object. 然后b[0]
和a
变量引用同一对象。
a[:foo] = :bar
b #=> [{:foo => :bar}]
Now the reason why it seemed to work differently in your first example is that assignment does not modify the object, but rather changes the reference itself. 现在,它在您的第一个示例中似乎有所不同的原因是,赋值不会修改对象,而是会更改引用本身。
a = []
b = '1'
a.push(b)
Now both a[0]
and b
are pointing to the very same object. 现在, a[0]
和b
都指向同一对象。 However if you do: 但是,如果您这样做:
b = '2'
You create a new string and changes the reference for variable b
, but a[0]
is still referencing the old string. 您创建了一个新字符串并更改了变量b
的引用 ,但是a[0]
仍在引用旧字符串。 However, if instead of changeng the reference you execute some modifying method: 但是,如果您不是更改参考,而是执行一些修改方法:
b.replace('2')
You'll see it will give you: 您会看到它会为您提供:
a #=> ['2']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.