在Julia中向函数内的矩阵添加一行(并将更改传播到外部)?

时间:2016-04-19 20:37:57

标签: matrix julia

这与此问题类似:

Add a row to a matrix in Julia?

但是现在我想在一个函数中增长矩阵:

public class DataTypes {
    public static void main(String[] argv) {
        // new feature in JDK 7
        int x = 0b1010; // 12
        int y = 0b1010_1010;
        int ssn = 444_12_7691;
        long phone = 408_777_6666L;
        double num = 9_632_401_909.1_0_3;
        String twoLine = "line one\nline two";
    }
}

现在,在此功能之外:

function f(mat)
    mat = vcat(mat, [1 2 3])
end

但这不起作用。对mat = [2 3 4] f(mat) 内的mat所做的更改不会传播到外部,因为在f内创建了新的mat(请参阅http://docs.julialang.org/en/release-0.4/manual/faq/#functions)。

有可能做我想做的事吗?

2 个答案:

答案 0 :(得分:7)

多维数组的大小不能更改。共享数据pointer hacks,但这些数据不会修改原始数组的大小。

即使有可能,也要注意因为Julia矩阵是列专业,这个操作非常慢,并且需要数组的副本。

在Julia中,修改传入数据的操作(即,在数据上执行计算而不是使用数据执行)通常标有!。这表示程序员将修改正在处理的集合。这些类型的操作通常称为“就地”操作,因为虽然它们更难以使用和推理,但它们避免使用额外的内存,并且通常可以更快地完成。

由于矩阵存储在内存中,因此无法避免此操作的副本。因此,将此特定操作转换为就地操作并没有多少实际好处。因此,我建议不要这样做。

如果确实出于某种原因需要此操作,则不应使用矩阵,而应使用向量向量:

v = Vector{Float64}[]
push!(v, [1.0, 2.0, 3.0])

此数据结构的访问速度稍慢,但 更快才能添加。

另一方面,从听起来来看,您可能对更专业的数据结构感兴趣,例如DataFrame

答案 1 :(得分:0)

我同意凤阳的非常全面的回答和出色的避免XY Problem。只需添加我的2¢。

push!是一个相当昂贵的操作,因为在每次推送时需要找到内存中的新位置以容纳更大尺寸的新变量。

如果你关心效率,那么预先分配你的mat并在你的函数中改变它(即改变它的内容)会更加谨慎,其中允许,即

julia> mat = Array(Int64, (100,3)); # mat[1,:] contains garbage values
julia> f(mat, ind, x) = mat[ind,:] = x;
julia> f(mat, 1, [1 2 3]);          # mat[1,:] now contains [1,2,3]

如果您更喜欢push!方法的原因是因为您不想跟踪索引并手动传递,那么您也可以通过保留来自动执行此过程。 mutatable 计数器,例如

function f(mat, c, x)
  c[1] = c[1] + 1;
  mat[c[1], :] = x;
end;

julia> mat = Array(Int64, (100,3)); counter = [0];
julia> f(mat, counter, [1 2 3]);
julia> f(mat, counter, [1 2 3]);
julia> f(mat, counter, [1 2 3]);
julia> mat[1:3,:]
  3×3 Array{Int64,2}:
   1  2  3
   1  2  3
   1  2  3

或者,您甚至可以创建一个闭包,即具有 state 的函数,它具有内部计数器,并且忘记保持外部计数器变量,例如

julia> f = () -> (); # creating an f at 'outer' scope
julia> let c = 1     # creates c at local 'let' scope
         f = (mat, x) -> (mat[c,:] = x; c += 1;) # f reassigned from outer scope
       end;          # f now contains the 'closed' variable c 
julia> mat = Array(Int64, (100,3));
julia> f(mat, [1 2 3]);
julia> f(mat, [2 3 4]);
julia> f(mat, [3 4 5]);
julia> mat[1:3,:]
  3×3 Array{Int64,2}:
   1  2  3
   2  3  4
   3  4  5