使用!push更新和存储全局Julia数组

时间:2019-01-14 17:58:37

标签: arrays julia push global read-eval-print-loop

我对Julia 1.0.3处理全局变量的方式感到有些困惑。有没有一种方法可以使用!push来更新全局数组?

在REPL中玩游戏时,我想更新一个全局变量,然后将结果push!到一个全局数组中进行存储。

var = [1]
res = []

for i in 1:5
  global var
  global res
  push!(var,i)
  print(string(var,"\n"))
  push!(res,var)
end

但是,存储在res中的值如下:

 [1, 1, 2, 3, 4, 5]
 [1, 1, 2, 3, 4, 5]
 [1, 1, 2, 3, 4, 5]
 [1, 1, 2, 3, 4, 5]
 [1, 1, 2, 3, 4, 5]

我希望这样:

[1, 1]
[1, 1, 2]
[1, 1, 2, 3]
[1, 1, 2, 3, 4]
[1, 1, 2, 3, 4, 5]

特别令人费解的是,行为似乎是变量而不是数组的预期结果:

var = 1
res = []

for i in 1:5
  global var
  global res
  var = var + i
  print(string(var,"\n"))
  push!(res, var)
end

给出预期结果的地方

  2
  4
  7
 11
 16

我显然错过了一些东西。

1 个答案:

答案 0 :(得分:2)

您正在将相同的var数组推入res数组中的每个位置。例如:

julia> var = [1]
1-element Array{Int64,1}:
 1

julia> res = [var, var]
2-element Array{Array{Int64,1},1}:
 [1]
 [1]

julia> var[1] = 2
2

julia> res
2-element Array{Array{Int64,1},1}:
 [2]
 [2]

res数组中的两个元素都是 var本身。因此,如果您修改var(使用push!或索引分配等方式),那么无论您如何访问它,您都会看到这些修改。

这不会发生在数字上,因为您不能自己修改数字。您可以更改存储在数组中的哪个数字,但是不能更改数字1来表示2到以前使用过1的任何地方-那就是等同于这里发生的事情。

要解决此问题,您通常只想在for循环内(而不是在循环外)创建var数组。但是在这种情况下,由于您要迭代地将内容添加到var并希望保存该中间状态,因此可以使用copy

julia> for i in 1:5
         global var
         global res
         push!(var,i)
         print(string(var,"\n"))
         push!(res,copy(var))
       end
Any[1]
Any[1, 2]
Any[1, 2, 3]
Any[1, 2, 3, 4]
Any[1, 2, 3, 4, 5]

julia> res
5-element Array{Any,1}:
 Any[1]
 Any[1, 2]
 Any[1, 2, 3]
 Any[1, 2, 3, 4]
 Any[1, 2, 3, 4, 5]