在Julia中复制或克隆一个集合

28
我已经在Julia中创建了一个一维数组(向量),即a=[1, 2, 3, 4, 5]。现在我想要创建一个新的向量b,使得b中的元素与a完全相同,即b=[1, 2, 3, 4, 5]
似乎直接使用b = a只是为原始集合创建一个指针,这意味着如果我修改b并且a可变,则修改也会反映在a中。例如,如果我使用!pop(b),则b=[1, 2, 3, 4]a=[1, 2, 3, 4]
我想知道是否有官方函数仅用于复制或克隆集合,使得对b的更改不会发生在a中。我发现一种解决方法是使用b = collect(a)。我会感激其他人提供其他方法。

你是来自 R 语言的对吧? - colinfang
@colinfang,不完全是。但作为一名生物统计学家,我必须使用R与合作者合作。 - Conta
3个回答

22

b=copy(a)

这行代码会实现你的想法。

methods(copy) 可以列出 copy 的方法列表,从而告诉你哪些类型的 a 可以使用这个方法。

julia> methods(copy)
# 32 methods for generic function "copy":
copy(r::Range{T}) at range.jl:324
copy(e::Expr) at expr.jl:34
copy(s::SymbolNode) at expr.jl:38
copy(x::Union{AbstractString,DataType,Function,LambdaStaticData,Number,QuoteNode,Symbol,TopNode,Tuple,Union}) at operators.jl:194
copy(V::SubArray{T,N,P<:AbstractArray{T,N},I<:Tuple{Vararg{Union{AbstractArray{T,1},Colon,Int64}}},LD}) at subarray.jl:29
copy(a::Array{T,N}) at array.jl:100
copy(M::SymTridiagonal{T}) at linalg/tridiag.jl:63
copy(M::Tridiagonal{T}) at linalg/tridiag.jl:320
copy{T,S}(A::LowerTriangular{T,S}) at linalg/triangular.jl:36
copy{T,S}(A::Base.LinAlg.UnitLowerTriangular{T,S}) at linalg/triangular.jl:36
copy{T,S}(A::UpperTriangular{T,S}) at linalg/triangular.jl:36
copy{T,S}(A::Base.LinAlg.UnitUpperTriangular{T,S}) at linalg/triangular.jl:36
copy{T,S}(A::Symmetric{T,S}) at linalg/symmetric.jl:38
copy{T,S}(A::Hermitian{T,S}) at linalg/symmetric.jl:39
copy(M::Bidiagonal{T}) at linalg/bidiag.jl:113
copy(S::SparseMatrixCSC{Tv,Ti<:Integer}) at sparse/sparsematrix.jl:184
copy{Tv<:Float64}(A::Base.SparseMatrix.CHOLMOD.Sparse{Tv<:Float64}, stype::Integer, mode::Integer) at sparse/cholmod.jl:583
copy(A::Base.SparseMatrix.CHOLMOD.Dense{T<:Union{Complex{Float64},Float64}}) at sparse/cholmod.jl:1068
copy(A::Base.SparseMatrix.CHOLMOD.Sparse{Tv<:Union{Complex{Float64},Float64}}) at sparse/cholmod.jl:1069
copy(a::AbstractArray{T,N}) at abstractarray.jl:349
copy(s::IntSet) at intset.jl:34
copy(o::ObjectIdDict) at dict.jl:358
copy(d::Dict{K,V}) at dict.jl:414
copy(a::Associative{K,V}) at dict.jl:204
copy(s::Set{T}) at set.jl:35
copy(b::Base.AbstractIOBuffer{T<:AbstractArray{UInt8,1}}) at iobuffer.jl:38
copy(r::Regex) at regex.jl:65
copy(::Base.DevNullStream) at process.jl:98
copy(C::Base.LinAlg.Cholesky{T,S<:AbstractArray{T,2}}) at linalg/cholesky.jl:160
copy(C::Base.LinAlg.CholeskyPivoted{T,S<:AbstractArray{T,2}}) at linalg/cholesky.jl:161
copy(J::UniformScaling{T<:Number}) at linalg/uniformscaling.jl:17
copy(A::Base.SparseMatrix.CHOLMOD.Factor{Tv}) at sparse/cholmod.jl:1070

1
谢谢 Shashi,copy() 真的很有帮助,也是我所需要的。我发现它仅在 Julia 文档的多维数组部分有记录,而在集合和数据结构部分没有。 - Conta

16
您可以使用copydeepcopy函数:
help?> copy
search: copy copy! copysign deepcopy unsafe_copy! cospi complex Complex complex64 complex32 complex128 complement

  copy(x)

  Create a shallow copy of x: the outer structure is copied, but not all internal values. For example, copying an
  array produces a new array with identically-same elements as the original.

help?> deepcopy
search: deepcopy

  deepcopy(x)

  Create a deep copy of x: everything is copied recursively, resulting in a fully independent object. For example,
  deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling deepcopy
  on an object should generally have the same effect as serializing and then deserializing it.

  As a special case, functions can only be actually deep-copied if they are anonymous, otherwise they are just copied.
  The difference is only relevant in the case of closures, i.e. functions which may contain hidden internal
  references.

  While it isn't normally necessary, user-defined types can override the default deepcopy behavior by defining a
  specialized version of the function deepcopy_internal(x::T, dict::ObjectIdDict) (which shouldn't otherwise be used),
  where T is the type to be specialized for, and dict keeps track of objects copied so far within the recursion.
  Within the definition, deepcopy_internal should be used in place of deepcopy, and the dict variable should be
  updated as appropriate before returning.

像这样:

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

julia> b = copy(a); c = deepcopy(a);

julia> a[4][1] = 42;

julia> b    # copied
4-element Array{Any,1}:
 1
 2
 3
  [42,5,6]

julia> c    # deep copied
4-element Array{Any,1}:
 1
 2
 3
  [4,5,6]

注意帮助系统提示存在其他与复制相关的功能。

0

我倾向于进行逐元素复制,即使这可能不是非常高效:

b .= a

或者

@. b = a

甚至我曾经使用过非常“肮脏”的方法

b = 1 * a

这在Python中也可以工作。


我忘记对整个数组进行切片了!: b = a[:] - Daniel Duque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接