6.3. Logical Indexing#

6.3.1. Introduction to Logical indexing#

As an alternative to indexing an array by x[idx] where idx is an array of integers, logical indexing allows for the syntax x[choose] where choose is an array of booleans. The size of choose must be the length of the array (or more generally, the dimension it indexes into). Note that the result is identical to x[findall(choose)], but shorter to write and likely more efficient.

x = -11:11
y = sin.(x)
x = x[y .> 0]          # Only keep values of x where y=sin x is positive
11-element Vector{Int64}:
 -11
 -10
  -6
  -5
  -4
   1
   2
   3
   7
   8
   9
# Example: Consider the matrix
A = rand(-10:10, 3, 10)
3×10 Matrix{Int64}:
 2  -3  10   7   3   3  2  -8   9    7
 0  -4   3  -6   3   9  4   2   5   -6
 5  10   2  -9  -3  -8  5   8  -8  -10
# Compute a boolean array with `true` if the column sums are >=0
pick = sum(A, dims=1) .≥ 0
1×10 BitMatrix:
 1  1  1  0  1  1  1  1  1  0
# Create a new vector with only the columns of A given by the `pick` variable
# Note that since `pick` is a 2D vector (row vector), we use [:] before indexing
B = A[:, pick[:]]
3×8 Matrix{Int64}:
 2  -3  10   3   3  2  -8   9
 0  -4   3   3   9  4   2   5
 5  10   2  -3  -8  5   8  -8

6.3.2. Examples: Simplifying the Sieve of Eratosthenes function#

In our previous implementation, we used the code below to collect all the prime numbers:

    ...
    # Return an array with all prime numbers
    primes = Int64[]
    for i = 2:n
        if prime[i]
            push!(primes, i)
        end
    end
    primes
    ...

Using array comprehensions, we can replace this entire part of the code by a single line:

    primes = [ i for i = 2:n if prime[i] ]

or even simpler, since the list of primes is simply the indices of the true values in the array prime, we can use the findall function. However in our original implementation, prime[1] was set to true (since it was not used) so we have to first make sure the number 1 is not considered a prime. Then the code can be written as:

    prime[1] = false
    primes = findall(prime)

6.3.3. Example: Simplifying the dart-throwing function#

We previously used the following code to count the number of “hits”, that is, how many points in the vectors x,y are inside the unit circle:

# Determine if points are inside the circle (a "hit")
hits = 0
for i = 1:n
    if x[i]^2 + y[i]^2  1
        hits += 1
    end
end

Using the count function, this can be written as a single line of code:

hits = count(@. x^2 + y^2  1)

6.3.4. Example: Simplifying the poker hand flush code#

When simulating the poker hands, we used the following code to determine if all cards were of the same suit:

    same_suit = true
    for i = 2:5
        if suits[i]  suits[1]
            same_suit = false
            break
        end
    end

Using the all function, this can be simplified to a single line of code:

    same_suit = all(suits[2:5] .== suits[1])