为什么我的数组元素在这个循环中改变了?

时间:2014-11-12 19:56:27

标签: ruby arrays loops shuffle

这非常棒。每次运行此代码时,在循环的至少一次迭代中,我的shuffled_couples数组的一个元素被修改,弄乱了最终输出。我已经使用不是shuffling couples_array的产品的数组测试了这个,并且这些数组似乎没有受到影响。

我在循环内部的shuffled_couple处插入了一个数字数组,并且每次迭代时,shuffled_couples从该数字数组中获取了另一个值,从左到右:

couples_array = [
["Clyde", "Bonnie"],
["Paris", "Helen"],
["Romeo", "Juliet"]
]

shuffled_couples = couples_array.shuffle

couples_array.count.times do |idx|
  puts "before loop #{idx}, shuffled_couples = : #{shuffled_couples}"
  couples_array[idx][1] = shuffled_couples[idx][1]
  puts "after loop #{idx}, shuffled_couples = : #{shuffled_couples}"
  puts
end

puts
puts
puts "The final value of couples_array is #{couples_array}"

在循环0之前,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Bonnie"], ["Romeo", "Juliet"]]

循环0之后,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Helen"], ["Romeo", "Juliet"]]

在循环1之前,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Helen"], ["Romeo", "Juliet"]]

循环1之后,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Helen"], ["Romeo", "Juliet"]]

在循环2之前,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Helen"], ["Romeo", "Juliet"]]

循环2之后,shuffled_couples:

[["Paris", "Helen"], ["Clyde", "Helen"], ["Romeo", "Juliet"]]

couples_array的最终值是:

[["Clyde", "Helen"], ["Paris", "Helen"], ["Romeo", "Juliet"]]

这里发生了什么?我该如何解决?我正在运行Ruby 1.9.3。

3 个答案:

答案 0 :(得分:1)

它的行为与你告诉它完全一样。您必须记住,对于数组数组,外部数组实际上包含对内部数组的引用。让我们来看看其含义。

irb(main):001:0> couples_array = [
irb(main):002:1* ["Clyde", "Bonnie"],
irb(main):003:1* ["Paris", "Helen"],
irb(main):004:1* ["Romeo", "Juliet"]
irb(main):005:1> ]
=> [["Clyde", "Bonnie"], ["Paris", "Helen"], ["Romeo", "Juliet"]]
irb(main):006:0> 
irb(main):007:0* shuffled_couples = couples_array.shuffle
=> [["Romeo", "Juliet"], ["Clyde", "Bonnie"], ["Paris", "Helen"]]

此时,couples_array[0]shuffled_couples[1]都指向相同的数组,["Clyde", "Bonnie"]。如果我通过 引用来改变第二个元素,那么当从另一个引用访问/查看时,更改将是可见的。它是完全相同的数组,它只是被两条不同的路径访问。

irb(main):008:0> couples_array[0][1] = 42  # replace "Bonnie" with 42
=> 42
irb(main):009:0> couples_array
=> [["Clyde", 42], ["Paris", "Helen"], ["Romeo", "Juliet"]]
irb(main):010:0> shuffled_couples
=> [["Romeo", "Juliet"], ["Clyde", 42], ["Paris", "Helen"]]

在此示例中,couples_array[0]shuffled_couples[1]是完全相同的数组,它只是被两条不同的路径访问。如果你改组,根据抽签的运气你经常得到不同的具体比赛,但是进行的基本概念将保持不变。

答案 1 :(得分:0)

您似乎需要制作阵列的深层副本。您将两个阵列都指向同一个实例,因此在循环中编辑它们。如果您将随机行更改为:

shuffled_couples = couples_array.shuffle.clone

我想你会得到你期望的结果。有关在ruby中复制vs克隆的更多信息: https://coderwall.com/p/1zflyg/ruby-the-differences-between-dup-clone

答案 2 :(得分:0)

您必须先深入克隆您的数组。这意味着您必须克隆数组中的所有元素(不仅仅是数组本身):

shuffled_couples = couples_array.map { |element| element.clone }
shuffled_couples = shuffled_couples.sample