David Parks
David Parks

Reputation: 32061

How do you select a subset of an array based on a condition in Julia

How do you do simply select a subset of an array based on a condition? I know Julia doesn't use vectorization, but there must be a simple way of doing the following without an ugly looking multi-line for loop

julia> map([1,2,3,4]) do x
       return (x%2==0)?x:nothing
       end
4-element Array{Any,1}:
  nothing
 2
  nothing
 4

Desired output:

[2, 4]

Observed output:

[nothing, 2, nothing, 4]

Upvotes: 5

Views: 7385

Answers (4)

Lutfullah Tomak
Lutfullah Tomak

Reputation: 761

You are looking for filter. Here is an example an filter(x->x%2==0,[1,2,3,5]) returning [2].

Upvotes: 14

Suvar
Suvar

Reputation: 341

Another updated version:

v[v .% 2 .== 0]

Probably, for the newer versions of Julia, one needs to add broadcasting dot before both % and ==

Upvotes: 0

Michael Ohlrogge
Michael Ohlrogge

Reputation: 10980

You can use the find() function (or the .== syntax) to accomplish this. E.g.:

julia> x = collect(1:4)
4-element Array{Int64,1}:
 1
 2
 3
 4    

julia> y = x[find(x%2.==0)]
2-element Array{Int64,1}:
 2
 4

julia> y = x[x%2.==0]  ## more concise and slightly quicker
2-element Array{Int64,1}:
 2
 4

Note the .== syntax for the element-wise operation. Also, note that find() returns the indices that match the criteria. In this case, the indices matching the criteria are the same as the array elements that match the criteria. For the more general case though, we want to put the find() function in brackets to denote that we are using it to select indices from the original array x.

Update: Good point @Lutfullah Tomak about the filter() function. I believe though that find() can be quicker and more memory efficient. (though I understand that anonymous functions are supposed to get better in version 0.5 so perhaps this might change?) At least in my trial, I got:

x = collect(1:100000000);
@time y1 = filter(x->x%2==0,x);  
# 9.526485 seconds (100.00 M allocations: 1.554 GB, 2.76% gc time)    

@time y2 = x[find(x%2.==0)]; 
# 3.187476 seconds (48.85 k allocations: 1.504 GB, 4.89% gc time)

@time y3 = x[x%2.==0];
# 2.570451 seconds (57.98 k allocations: 1.131 GB, 4.17% gc time)    

Update2: Good points in comments to this post that x[x%2.==0] is faster than x[find(x%2.==0)].

Upvotes: 8

daycaster
daycaster

Reputation: 2697

There are element-wise operators (beginning with a "."):

julia> [1,2,3,4] % 2 .== 0
4-element BitArray{1}:
 false
  true
 false
  true

julia> x = [1,2,3,4]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> x % 2 .== 0
4-element BitArray{1}:
 false
  true
 false
  true

julia> x[x % 2 .== 0]
2-element Array{Int64,1}:
 2
 4

julia> x .% 2
4-element Array{Int64,1}:
 1
 0
 1
 0

Upvotes: 9

Related Questions