简体   繁体   English

数组/哈希异常行为

[英]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! ab都完全引用了某个对象!

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM