由于另一个数组,Ruby空数组会在迭代中更改值

时间:2017-08-08 09:48:36

标签: arrays ruby

在块外部定义空数组,在块内,将其分配给新变量。如果新数组发生更改,则空数组也会修改其值。为什么呢?

# THIS CODE CHECK WHICH LETTERS IN klas APPEAR IN docs
klas = ["a", "b", "c"]

docs = [[1, "a"], [2, "a"], [3, "b"], [4, "b"], [5, "c"], [6, "c"]]

output = []
empty_array = Array.new(klas.size) { 0 } # EMPTY ARRAY DEFINED HERE

docs.each do |doc|
    puts empty_array.inspect
    puts (output_row = empty_array).inspect # EMPTY ARRAY ASSIGNED TO ANOTHER

    # FIND INDEX OF THE LETTER IN klas FROM docs. ASSIGN 1.
    output_row[klas.index(doc[1])] = 1 # PROBLEM! THIS ALSO CHANGES THE EMPTY ARRAY VALUES
    output << output_row
end

CONSOLE OUTPUT显示空数组根据另一个数组

更改其值
###
empty_array is [0, 0, 0]
output_row is [0, 0, 0]
---
###
empty_array is [1, 0, 0]
output_row is [1, 0, 0]
---
###
empty_array is [1, 0, 0]
output_row is [1, 0, 0]
---
###
empty_array is [1, 1, 0]
output_row is [1, 1, 0]
---
###
empty_array is [1, 1, 0]
output_row is [1, 1, 0]
---
###
empty_array is [1, 1, 1]
output_row is [1, 1, 1]
---

# INCORRECT output IS
=> [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]
# SHOULD BE
=> [[1, 0, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 0, 1]]

但是如果在块中定义了空数组并将其分配给新变量,则它按预期工作。

docs.each do |doc|
    empty_array = Array.new(klas.size) { 0 } # THIS MAKES SURE empty_array stays with zero values
    output_row = empty_array    
    output_row[klas.index(doc[1])] = 1
    output << output_row
end

CORRECT output IS
=> [[1, 0, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 0, 1]]

为什么空数组在块外时修改其值?不管另一个阵列改变它的值,它不应该保持不变吗?

1 个答案:

答案 0 :(得分:4)

使用

output_row = empty_array

你没有复制空数组。您正在创建对empty_array中引用的相同基础数组的引用。

您可以创建克隆或数组的副本。所以使用:

output_row = empty_array.dup

这将创建一个新的数组,它与empty_array重复,请参阅http://ruby-doc.org/core-2.4.1/Object.html#method-i-dup

有关示例的更详细说明:

a = [1] => [1] # is creating a new array 'x'
               # a is referencing this array, a is not the array itself!

b = a   => [1] # b now references the array 'x'

a = [2] => [2] # is creating a new array 'y', a is referencing this new array
               # the reference of b is not changing

b       => [1] # b still pointing to array 'x'

因此,对于b = a,您只需告诉他们引用相同的数组x,但b不是对a的引用。