# Find indices meeting multiple criteria searching from multiple arrays

**URL:** <https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228>\
**Category:** General Usage\
**Tags:** arrays\
**Created:** [December 3, 2020, 11:36pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228 "2020-12-03T23:36:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![dalarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dalarev/32/9881_2.png) [@dalarev](https://discourse.julialang.org/u/dalarev)\
**Post date:** [December 3, 2020, 11:36pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/1 "2020-12-03T23:36:13Z")

</div>

How do I find the indices that meet both A \> 0 and B \> 0?

In this MWE, I want the answer `CartesianIndex(3,3)`, since that’s the only location that satisfies both conditions.

```julia
julia> A = repeat(-1:1',1,3)
3×3 Array{Int64,2}:
 -1 -1 -1
  0 0 0
  1 1 1

julia> B = A'
3×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
 -1 0 1
 -1 0 1
 -1 0 1

```

Maybe there is some way to do this with `findall` but the following was not working for me:

```julia
ind = findall(x -> x>0,A) && findall(x -> x>0,B)

```

---

<div class="post-metadata">

**Author:** ![cgeoga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cgeoga/32/216186_2.png) [@cgeoga](https://discourse.julialang.org/u/cgeoga)\
**Post date:** [December 3, 2020, 11:51pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/2 "2020-12-03T23:51:45Z")

</div>

I make no claim that this is fastest, but `intersect` instead of `&&` seems to fit the bill: `ind = intersect(findall(x -> x>0,A), findall(x -> x>0,B)`.

---

<div class="post-metadata">

**Author:** ![dalarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dalarev/32/9881_2.png) [@dalarev](https://discourse.julialang.org/u/dalarev)\
**Post date:** [December 4, 2020, 12:38am UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/3 "2020-12-04T00:38:34Z")

</div>

Nice, was not aware of intersect. Thanks!

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [December 4, 2020, 7:33am UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/4 "2020-12-04T07:33:15Z")

</div>

I would probably write it as

```julia
julia> findall((A .> 0) .& (B .> 0))
1-element Vector{CartesianIndex{2}}:
 CartesianIndex(3, 3)

```

(or forego the `findall` if you can work with the Boolean mask)

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [December 4, 2020, 2:15pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/6 "2020-12-04T14:15:03Z")

</div>

> [@cgeoga](#):
>
> I make no claim that this is fastest, but `intersect` instead of `&&` seems to fit the bill: `ind = intersect(findall(x -> x>0,A), findall(x -> x>0,B)` .

This creates unnecessary extra closures - `>(0)` already creates a curried version 🙂

> [@nilshg](#):
>
> I would probably write it as
> 
> ```julia
> julia> findall((A .> 0) .& (B .> 0))
> 1-element Vector{CartesianIndex{2}}:
> CartesianIndex(3, 3)
> 
> ```
> 
> (or forego the `findall` if you can work with the Boolean mask)

This has to allocate the resulting mask, which is potentially slower (since it has to iterate twice, once to create the mask and once to find the indices).

```julia
julia> using BenchmarkTools

julia> @btime intersect(findall(x -> x>0,$A), findall(x -> x>0,$B))
  885.417 ns (19 allocations: 1.84 KiB)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(3, 3)

julia> @btime intersect(findall(>(0),$A), findall(>(0),$B))
  868.421 ns (18 allocations: 1.83 KiB)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(3, 3)

julia> greater0(A,B) = findall((A .> 0) .& (B .> 0))
greater0 (generic function with 1 method)

julia> @btime greater0($A,$B)
  112.854 ns (3 allocations: 240 bytes)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(3, 3)

```

If you want to go for speed, something like this might be best, which stays fast even with huge arrays:

```julia
julia> findGreater0(A,B) = [idx for idx in CartesianIndices(A) if @inbounds (A[idx] > 0 && B[idx] > 0) ]
findGreater0 (generic function with 1 method)

julia> A = repeat(-1:1',1,3)
3×3 Array{Int64,2}:
 -1 -1 -1
  0 0 0
  1 1 1

julia> B = A';

julia> @btime findGreater0($A,$B)
  93.085 ns (3 allocations: 240 bytes)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(3, 3)

julia> B = copy(A'); # manifest the adjoint

julia> @btime findGreater0($A,$B)
  95.364 ns (3 allocations: 240 bytes) # staying fast!
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(3, 3)

julia> A = zeros(Int,10000,10000);

julia> A[1,:] .= -1;

julia> A[end,:] .= 1;

julia> B = A';

julia> @btime greater0($A,$B)          
  1.230 s (5 allocations: 11.93 MiB)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(10000, 10000)

julia> @btime findGreater0($A,$B)
  116.800 ms (3 allocations: 240 bytes)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(10000, 10000)

```

Julias Adjoint is lazy, so that’s why creating and iterating the bitmask becomes very sluggish - the memory is not accessed in an optimal manner. Iterating with `CartesianIndices` skips that problem entirely.

Manifesting the adjoint makes it almost as fast as the generator version - the difference being the extra iteration that has to be done as well as the big allocation (that might not be possible if we run out of memory):

```julia
julia> B = copy(A'); # manifest the adjoint (10000x10000 array)

julia> @btime greater0($A,$B)
  128.834 ms (5 allocations: 11.93 MiB)
1-element Array{CartesianIndex{2},1}:
 CartesianIndex(10000, 10000)

```

Note that there’s not really much more that could be done here - since we don’t know when the condition will be true, SIMD will be a little hard to do since it’s effectively a coin flip whether or not a given index will be included or not.

---

<div class="post-metadata">

**Author:** ![dalarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dalarev/32/9881_2.png) [@dalarev](https://discourse.julialang.org/u/dalarev)\
**Post date:** [December 4, 2020, 3:38pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/7 "2020-12-04T15:38:46Z")

</div>

> [@Sukera](#):
>
> `julia> greater0(A,B) = findall((A .> 0) .& (B .> 0))`

Thanks for this. I’ll be using this function since my arrays won’t be large.

---

<div class="post-metadata">

**Author:** ![leon](https://avatars.discourse-cdn.com/v4/letter/l/dc4da7/32.png) [@leon](https://discourse.julialang.org/u/leon)\
**Post date:** [October 23, 2021, 3:49pm UTC](https://discourse.julialang.org/t/find-indices-meeting-multiple-criteria-searching-from-multiple-arrays/51228/8 "2021-10-23T15:49:59Z")

</div>

Best solution for speed for sure! Many thanks for sharing.
