Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find indices of non-zero elements from [1,2,0,0,4,0] in julia and create an Arrray with them

Tags:

julia

I know there is a function that does this, for example:

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

 3-element Array{Int64,1}:
 1
 2
 5

I am trying to do it on my own way, however, I am stuck here

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

Thanks in advance.

like image 610
Pau Avatar asked Dec 06 '22 15:12

Pau


2 Answers

Here's one alternative:

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

It actually outperformed find for all the cases I tested, though for the very small example vector you posted, the difference was negligible. There is perhaps some performance advantage to avoiding the branch and dynamically growing the index array.

like image 119
DNF Avatar answered Mar 11 '23 18:03

DNF


I have notice that the question is really confusion (because is poorly formulated, sorry about that). Therefore, there are two possible answers: one is [1,2,4]which is an array with the non-zero elements; the other is [1,2,5] which is an array of the indices of the non-zero elements.

Let´s begin with the first option

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

for i=1:endof(A)
    if A[i] != 0
        push!(B,i)
    end
end
println(B)

The output is Any[1,2,5]

However, the type is not the one I wanted. Using typeof(B) it shows Array{Any,1} so I added this code:

B = Array{Int64}(B)
println(B)
typeof(B)

And the result is the desired

[1,2,5]
Array{Int64,1}

To improve its efficiency, following with the recommendations in the comments, I have specified the type of B with the eltype() function before the loop as follows:

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)

Then, the output is again the desired

[1,2,5]
Array{Int64,1}

The simplest way of doing this is using the function find(). However, since I´m a beginner, I wanted to do it in another way. However, there is another alternative provided by @DNF that outperform find() for the cases he has tested it (see below answers).

The second option, which creates an output matrix with the non-zero elements has been provided by other users (@Harrison Grodin and @P i) in this discussion.

Thanks all of you for the help!

like image 22
Pau Avatar answered Mar 11 '23 18:03

Pau