为什么`selectperm!`做的事与`selectperm`不同?

时间:2018-02-27 10:12:29

标签: sorting julia permutation

我想在循环中使用selectperm,根据矩阵每列中t个最小元素的索引做一些事情(比如说t = 3):

julia> a = rand(10, 10);
julia> for i in indices(a, 2)
         println(selectperm(view(a, :, i), 1:3))
       end
[9, 7, 6]
[3, 2, 6]
[8, 3, 1]
[4, 7, 6]
[4, 9, 10]
[6, 10, 8]
[10, 8, 9]
[10, 5, 6]
[1, 2, 9]
[5, 8, 10]

认为每次分配索引向量会更好地避免(实际上我不使用它们进行打印),我尝试使用预分配的数组作为结果 - 但是返回完全不同的值:

julia> cache = Vector{Int}(3);
julia> for i in indices(a, 2)
           selectperm!(cache, view(a, :, i), 1:3)
           println(cache)
       end
[3, 1, 2]
[3, 2, 1]
[3, 1, 2]
[3, 1, 2]
[1, 3, 2]
[2, 1, 3]
[1, 2, 3]
[2, 1, 3]
[1, 2, 3]
[3, 2, 1]

那么,这里发生了什么?我如何正确使用selectperm!

1 个答案:

答案 0 :(得分:0)

对于!的函数而言,selectperm!的“预分配索引向量”参数存储结果的位置 - 或者至少,不仅如此。此参数在内部用于创建所有索引的部分permuatation,然后 subindexed 使用给定的k参数描述您要选择的索引(在我们的案例1:3中为三个最小的)。从code可以很容易地看出这一点。结果看起来合理但错在这里只是一个意外;以下内容会更具启发性:

julia> cache = Vector{Int}(3);
julia> for i in indices(a, 2)
           selectperm!(cache, view(a, :, i), 4:6)
           println(cache)
       end
ERROR: BoundsError: attempt to access 3-element Array{Int64,1} at index [4:6]
Stacktrace: <...>

所以,为了在这里利用它,我们必须预先分配一个包含所有索引的向量(即a列),然后该索引向量将是每次都是变换的。另外,传递initialized = true可以避免每次填写索引。

julia> cache = collect(indices(a, 2));
julia> for i in indices(a, 2)
           ix = selectperm!(cache, view(a, :, i), 1:3, initialized = true)
           println(ix)
       end
[9, 7, 6]
[3, 2, 6]
[8, 3, 1]
[4, 7, 6]
[4, 9, 10]
[6, 10, 8]
[10, 8, 9]
[10, 5, 6]
[1, 2, 9]
[5, 8, 10]