Arrays 为什么str.next!在可枚举映射中,是否用相同的元素填充数组?

Arrays 为什么str.next!在可枚举映射中,是否用相同的元素填充数组?,arrays,ruby,hashtable,Arrays,Ruby,Hashtable,Enumerable#map生成一个数组,其中包含块中的返回值 在这种情况下,可以说: v = 'a' 26.times.map { |i| v.ord.+(i).chr } # => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] 但是为什么以下代码用相同的元素填充数组 v

Enumerable#map
生成一个数组,其中包含块中的返回值

在这种情况下,可以说:

v = 'a'
26.times.map { |i| v.ord.+(i).chr }

# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
但是为什么以下代码用相同的元素填充数组

v = '`'
26.times.map { v.next! }

# => ["z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z"]
它们不是都应该有a到z元素吗

同样,这是有效的:

v = '`'
Array.new(26) { v = v.succ }

# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
实际上,我正在努力做到:

v = "\xf0\x9d\x93\xa9"
('a'..'z').reduce({}) { |h, i| h.merge(i.intern => v = v.succ) }

# => {:a=>"When you call 
next!
or
succ!
on a variable
str
, object assigned to this variable is mutated and a reference to this object is returned. If
str = 'a'
and you call
str.next!
26 times, str becomes
z
. Every time
next!
is called, a reference to the same object is returned. As a result, you get an array of 26 references to the same object. That's why all of the elements in the array are the same.

You can test that by checking
object_id
of array elements:

pry(main)> str = 'a'
'a'
pry(main)> array = 3.times.map{ str.next!}
=> ["d", "d", "d"]
pry(main)> array.map(&:object_id)
=> [47056742362940, 47056742362940, 47056742362940]
pry(main)> array.map(&:object_id).uniq
=> [47056742362940]
v=“\xf0\x9d\x93\xa9”
('a'..'z').reduce({}){h,i{h.merge(i.intern=>v=v.succ)}

#=>{:a=>"当您对变量
str
调用
next!
succ!
时,分配给此变量的对象将发生变化,并返回对此对象的引用。如果
str='a'
并且您调用
str.next!
26次,str将变为
z
。每次调用
next!
时,都会返回对同一对象的引用结果,您将得到一个包含26个对同一对象的引用的数组。这就是数组中所有元素都相同的原因

您可以通过检查数组元素的
object\u id
来测试:

[39] pry(main)> str << "b"
=> "db"
[40] pry(main)> array
=> ["db", "db", "db"]
[41] pry(main)> str.replace
str.replace
[41] pry(main)> str.replace('a')
=> "a"
[42] pry(main)> array
=> ["a", "a", "a"]
编辑
str
时,将更新所有数组元素:

[25] pry(main)> str = 'a'
=> "a"
[26] pry(main)> 25.times.map{ str.next!.dup} 
=> ["b",
 "c",
 "d",
 "e",
 "f",
 "g",
 "h",
 "i",
 "j",
 "k",
 "l",
 "m",
 "n",
 "o",
 "p",
 "q",
 "r",
 "s",
 "t",
 "u",
 "w",
 "x",
 "y",
 "z"]
您还可以使用以下范围:


关于您的问题:
(:a..:z).zip(‘是的,这很酷!但是为什么赋值运算符工作时bang方法不工作呢?它工作,但是你有一个数组引用同一个对象26次,而不是一个包含26个不同对象的数组。见下文。哦,太棒了!所以在这种情况下,当你将数组赋值为
a
,那么如果你写
z.replace('hello'))
整个数组
a
填充“hello”!…类似于
a.fill(“hello”)
我已经更新了答案,以涵盖对象的更改。
[25] pry(main)> str = 'a'
=> "a"
[26] pry(main)> 25.times.map{ str.next!.dup} 
=> ["b",
 "c",
 "d",
 "e",
 "f",
 "g",
 "h",
 "i",
 "j",
 "k",
 "l",
 "m",
 "n",
 "o",
 "p",
 "q",
 "r",
 "s",
 "t",
 "u",
 "w",
 "x",
 "y",
 "z"]
[32] pry(main)> ('a'..'z').to_a
=> ["a",
 "b",
 "c",
 "d",
 "e",
 "f",
...