从julia中的[1,2,0,0,4,0]中查找非零元素的索引,并使用它们创建一个Arrray

从julia中的[1,2,0,0,4,0]中查找非零元素的索引,并使用它们创建一个Arrray,julia,Julia,我知道有一个函数可以做到这一点,例如: A = [1,2,0,0,4,0] find(A) 3-element Array{Int64,1}: 1 2 5 我试着用我自己的方式去做,但是,我被困在这里了 for i=1:endof(A) if A[i] != 0 [] end end 提前谢谢。我注意到这个问题真的很混乱(因为表述不当,很抱歉)。所以,有两个可能的答案:一个是[1,2,4],它是一个包含非零元素的数组;另一个是[1,2,5],它是非零元素索引

我知道有一个函数可以做到这一点,例如:

A = [1,2,0,0,4,0]
find(A)

 3-element Array{Int64,1}:
 1
 2
 5
我试着用我自己的方式去做,但是,我被困在这里了

for i=1:endof(A)
   if A[i] != 0
      []
   end
end

提前谢谢。

我注意到这个问题真的很混乱(因为表述不当,很抱歉)。所以,有两个可能的答案:一个是
[1,2,4]
,它是一个包含非零元素的数组;另一个是
[1,2,5]
,它是非零元素索引的数组

让我们从第一个选项开始

A = [1,2,0,0,4,0]
B = []

for i=1:endof(A)
    if A[i] != 0
        push!(B,i)
    end
end
println(B)
输出为
Any[1,2,5]

但是,类型不是我想要的。使用
typeof(B)
显示
Array{Any,1}
,因此我添加了以下代码:

B = Array{Int64}(B)
println(B)
typeof(B)
结果是理想的

[1,2,5]
Array{Int64,1}
为了提高其效率,根据注释中的建议,我在循环之前使用
eltype()
函数指定了B的类型,如下所示:

A1 = [1,2,0,0,4,0] #The default type is Array{Int64,1}
B1 = eltype(A1)[] #Define the type of the 0 element array B with the type of A
#B1 = eltype(typeof(A))[] this is also valid
for i=1:endof(A1)
    if A1[i] != 0
        push!(B1::Array{Int64,1},i::Int64)
    end
end
println(B1)
typeof(B1)
然后,输出再次是所需的

[1,2,5]
Array{Int64,1}
最简单的方法是使用函数
find()
。然而,由于我是一个初学者,我想用另一种方式来做。然而,@DNF提供的另一个替代方案在他测试过的案例中表现优于
find()
(参见下面的答案)

其他用户(@Harrison Grodin和@pi)在本次讨论中提供了第二个选项,它创建了一个包含非零元素的输出矩阵


谢谢大家的帮助

这里有几个选项

使用您开始使用的策略,您可以使用
push
for
循环中

julia> B = Int[]
0-element Array{Int64,1}

julia> for element = A
           if element != 0
               push!(B, element)
           end
       end

julia> B
3-element Array{Int64,1}:
 1
 2
 4
您也可以选择使用短路评估

julia> for element = A
           element != 0 && push!(B, element)
       end

julia> for element = A
           element == 0 || push!(B, element)
       end
filter
和列表理解也是有效的

julia> B = [element for element = A if element != 0]
3-element Array{Int64,1}:
 1
 2
 4

julia> filter(n -> n != 0, A)
3-element Array{Int64,1}:
 1
 2
 4

编辑:由于OP的评论,我意识到期望的结果是非零元素的索引,而不是元素本身。这可以通过以下简单方法实现:


这里有一个选择:

function myfind(c)
    a = similar(c, Int)
    count = 1
    @inbounds for i in eachindex(c)
        a[count] = i
        count += (c[i] != zero(eltype(c)))
    end
    return resize!(a, count-1)
end

在我测试的所有案例中,它实际上都优于
find
,尽管对于您发布的非常小的示例向量,差异可以忽略不计。避免分支和动态增长索引数组可能有一些性能优势。

您能解释一下问题所在吗?您正在寻找
推送?您还可以使用
@less find(a)
查看
find
的源代码。我希望社区不要急于否决新成员@用户7546279,选择一个昵称,我们会更爱你。看看
B=A[A.!=0]
也能用(谢谢@Ismael VC)实际上
B=A[A.!=0]
不是我想要的。这样做是为了排除零元素。我想做的是用非零元素的索引创建一个数组,而不是用非零元素。我下面的回答也不正确。所需输出应为
[1,2,5]
,对应于
1
2
4
的位置。很抱歉,我注意到这个问题太复杂了。要从一开始就获得正确的类型,您可以使用
B=eltype(A)[]
。最后看一看。特别是,在全局范围内执行操作的速度很慢。再次感谢您,这些操作对我帮助很大。请注意,您不需要重新分配推送的结果!(B…)
返回
B
。那个表示修改了第一个参数。问题是我注意到问题不太清楚。我想要的是一个包含非零元素索引的数组,而不是一个非零元素数组。不过,非常感谢你!这太有用了。@Pau啊,我明白了!我已经更新了我的回复,加入了寻找指数的解决方案。希望有帮助!:)您可以在数组
a
上调用
countnz
,以获取数组中非零的
n
,然后用正确的维度预先分配
a
。当然,但是您必须在数组上花费额外的时间,这似乎是白费力气。基本上,这将是工作的两倍。我想这取决于您希望优化的性能的特定方面。我的建议反映了我对最小化内存事务的偏好
countnz
不分配内存,使用它预分配
a
只使用必要的内存。
function myfind(c)
    a = similar(c, Int)
    count = 1
    @inbounds for i in eachindex(c)
        a[count] = i
        count += (c[i] != zero(eltype(c)))
    end
    return resize!(a, count-1)
end