【问题标题】:Iterating over a concatenated array alters the items in the original arrays. Why?迭代连接数组会改变原始数组中的项目。为什么?
【发布时间】:2015-06-06 23:31:38
【问题描述】:

我在使用 Ruby 数组时遇到了一些意外行为:

array1 = ["a"]
array2 = ["b"]
array3 =  array1 + array2

puts "array1 before array3.map!: #{array1}"
puts "array2 before array3.map!: #{array2}"
puts "array3 before array3.map!: #{array3}"

array3.map! { |item| item << "_modified" }

puts "array1  after array3.map!: #{array1}"
puts "array2  after array3.map!: #{array2}"
puts "array3  after array3.map!: #{array3}"

终端输出:

array1 before array3.map!: ["a"]
array2 before array3.map!: ["b"]
array3 before array3.map!: ["a", "b"]
array1  after array3.map!: ["a_modified"]                #Unexpected
array2  after array3.map!: ["b_modified"]                #Unexpected
array3  after array3.map!: ["a_modified", "b_modified"]  #Expected

第一个问题:为什么 array1 和 array2 中的项目不同,尽管只对 array3 进行了迭代?连接两个数组会返回一个新数组,那么为什么对array1 和array2 有挥之不去的影响呢?

第二个问题:如何在不改变array1或array2的项目的情况下,通过迭代改变array3中的项目?

第三个问题:当使用 .map 和 .each 代替 .map! 时,输出是相同的。所以看起来 .each 和 .map 正在改变数组中的项目。为什么会出现这种情况?

【问题讨论】:

  • 定义三个数组后得到:array1.map(&amp;:object_id) #=&gt; [70229175091960]; array2.map(&amp;:object_id) #=&gt; [70229175065880]; array3.map(&amp;:object_id) #=&gt; [70229175091960, 70229175065880]。这有帮助吗?

标签: ruby arrays loops concatenation concat


【解决方案1】:

array1array2 不会被修改。字符串"a""b" 被修改。

这样看:

string = "a"
array = [string, string, string] # ["a", "a", "a"]
string << "b"
array # ["ab", "ab", "ab"]

数组没有改变。它仍然是[string, string, string]。但string 不同。

编辑为了澄清,并从 cmets 重复,您没有修改数组。这是在修改数组:

array3.each_index { |index| array3[index] = item + "_modified" }

当您将每个元素替换为另一个元素时。当您执行此操作时,array1array2 打印不变 - 它们的元素被踢出 array3 并被其他内容替换。你做了什么:

array3.map! { |item| item << "_modified" }

"_modifier" 附加到每个项目(不会弄乱其标识),然后map!array3 中的每个元素替换为相同的元素。因此,array3 仍然具有与 array1array2 相同的元素,并且其中一个的任何更改都会反映在另一个中。

【讨论】:

  • 我以为修改数组中的一个项正是修改数组的意思。
  • 好吧,假设你有一个有 3 个娃娃的娃娃屋。你将其中一个娃娃浸入蓝色油漆中。娃娃屋是改装的吗?它仍然拥有与以前相同的三个娃娃。当然,它看起来不同(就像 array1 打印出来时看起来不同),但它的内容与以前相同。
  • 令数组 = [1,2,3]。如果array.map! { |价值| i * 2 } ,则表示从现在开始修改数组,数组为[2,4,6]。
  • Welp,现在你处于一个非常不同的领域,因为数字是不可变的,而字符串是可变的。 “修改数组”意味着添加、删除或替换一个元素,item &lt;&lt; "_modified" 没有做这些。您的数组仍然包含相同的元素,但这些元素本身是不同的。
  • 我刚刚看到你的评论编辑。实际上,array.map! { |val| i * 2 } 将修改数组:i * 2 创建一个与 2 不同的新数字 4(而不是将 2 修改为 4),然后替换具有新值的数组元素。在您的情况下,关键问题是您将元素替换为 same 对象(您对其进行了路过式的残缺),因此数组保持不变。一定要看到x&lt;&lt;y(修改x,通过附加y并返回x)和x+y(连接xy返回一个新字符串)之间的区别。
猜你喜欢
  • 2019-07-27
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 2019-10-14
  • 2021-11-03
  • 1970-01-01
  • 2016-06-24
相关资源
最近更新 更多