📜  Julia 中的逻辑和笛卡尔索引

📅  最后修改于: 2021-11-25 04:36:31             🧑  作者: Mango

与大多数技术计算语言一样,Julia 提供了一流的数组实现,其中包含非常重要的函数,使处理 N 维数组变得非常容易。最新特性之一,基于点(.)的广播进行了大部分“重复”数组操作,即一行代码。

数组索引

Julia 中的数组索引与其对应项类似。
句法:

Julia 中的数组索引有两种类型:

  • 笛卡尔索引
  • 逻辑索引

笛卡尔索引

笛卡尔坐标给出了一个点在 1D、2D 或 3D 平面中的位置。笛卡尔指数有类似的行为。它们给出存储在 1D、2D、3D 或 nD 数组中的元素的值。
对于标量索引CartesianIndex{N}s ,表现得像一个 N 元组跨越多个维度的整数,而标量索引数组包括CartesianIndex{N}数组
句法:

CartesianIndex(i, j, k...)   -> I
CartesianIndex((i, j, k...)) -> I

上述语法创建了一个多维索引 I,可用于索引多维数组arr 。我们可以说, arr[I]等价于arr[i, j, k…] 。允许混合整数和CartesianIndex索引。
例子 :

arr[Ipre, i, Ipost] 
(where Ipre and Ipost are CartesianIndex indices and i is an Int) 
can be a useful expression when writing algorithms that work along a single dimension
of an array of arbitrary dimensionality.

标量笛卡尔索引

一维数组的笛卡尔索引:

# Create a 1D array of size 5
arr = reshape(Vector(1:2:10), (5))
  
# Select index number 1
arr[CartesianIndex(1)]
  
# Select index number 3
arr[CartesianIndex(3)]

输出:

二维数组的笛卡尔索引:

# Create a 2D array of size 3x2
arr = reshape(Vector(1:2:12), (3, 2))
  
# Select cartesian index 2, 2 
arr[CartesianIndex(2, 2)]
  
# Select index number 3, 1
arr[CartesianIndex(3, 1)]

输出:

3D 数组的笛卡尔索引:

# Create a 3D array of size 2x1x2
arr = reshape(Vector(1:2:8), (2, 1, 2))
  
# Select cartesian index 1, 1, 1
arr[CartesianIndex(1, 1, 1)]
  
# Select index number 1, 1, 2
arr[CartesianIndex(1, 1, 2)]

输出:

nD 数组的笛卡尔索引:

# Create a 5D array of size 2x2x1x2x2
arr = reshape(Vector(1:2:32), (2, 2, 1, 2, 2))
  
# Select cartesian index 1, 2, 1, 2, 2
arr[CartesianIndex(2, 2, 1, 2, 2)]

输出:

从上面的例子中,很明显CartesianIndex只是将多个整数收集到一个表示单个多维索引的对象中。
讨论了标量表示之后,让我们来谈谈CartesianIndex{N} 的数组,它表示每个跨越 N 维的标量索引的集合,这种索引形式被称为“逐点”索引。

基于数组的笛卡尔索引

一维数组的基于数组的笛卡尔索引:

# Create a 1D array of size 5
arr = reshape(Vector(2:6), 5)
  
# Select an array of cartesian indices 2, 3, 5
arr[[CartesianIndex(2), 
     CartesianIndex(3), CartesianIndex(5)]]

输出:

二维数组的基于数组的笛卡尔索引:

# Create a 2D array of size 5x6
arr = reshape(Vector(1:30), (5, 6))
  
# Select an array of cartesian indices (5, 2), (3, 6), (1, 4)
arr[[CartesianIndex(5, 2), 
     CartesianIndex(3, 6), CartesianIndex(1, 4)]]

输出:

用于 3D 数组的基于数组的笛卡尔索引:

# Create a 3D array of size 2x3x1
arr = reshape(Vector(1:12), (2, 3, 2))
  
# Select an array of cartesian indices (1, 2, 1), (2, 2, 2), (1, 3, 1)
arr[[CartesianIndex(1, 2, 1),
     CartesianIndex(1, 3, 1), CartesianIndex(2, 2, 2)]]

输出:

nD 数组的基于数组的笛卡尔索引:

# Create a 5D array of size 2x2x1x2x2
arr = reshape(Vector(1:2:32), (2, 2, 1, 2, 2))
  
# Select an array of cartesian indices 
# (1, 2, 1, 1, 1), (1, 2, 1, 2, 2), (2, 1, 1, 2, 1)
arr[[CartesianIndex(1, 2, 1, 1, 1), 
     CartesianIndex(1, 2, 1, 2, 2), 
     CartesianIndex(2, 1, 1, 2, 1)]]

输出:

这真的很有用,如果我们想选择数组中不按顺序的特定元素。但是如果我们有一个 1000 的数组并且我们需要提取 100 个元素,那会很乏味!
这就是dot(.)广播发挥作用的地方。

# Create a 3D array of size 3x3x3
arr = reshape(Vector(1:27), (3, 3, 3))
  
# Select diagonal elements in all the 
# 3 planes of cartesian coordinates
arr[[CartesianIndex(1, 1, 1), CartesianIndex(2, 2, 1), 
     CartesianIndex(3, 3, 1), CartesianIndex(1, 1, 2), 
     CartesianIndex(2, 2, 2), CartesianIndex(3, 3, 2),
     CartesianIndex(1, 1, 3), CartesianIndex(2, 2, 3), 
     CartesianIndex(3, 3, 3)]]
  
# Using dot broadcasting and (:)colon, to reduce code
arr[CartesianIndex.(axes(arr, 1), axes(arr, 2), :)]

输出:

我们在第三步中减少代码的效率有多高!!

我们应该如何处理笛卡尔索引?
我们观察到,CartesianIndices承担类似的方式接近resemblence到笛卡尔坐标和函数。
例子:

We have a 3D shape in space, and it is mapped out by storing the coordinates of it's 
edges in an array and we might want to mask out a region from the shape. It becomes 
easy to deal with by using CartesianIndices, since they resemble the coordinate system. 

逻辑索引

在计算/电子学中,基础是本质上具有确定性的逻辑。这是:

true, false
one, zero
on, off

它基本上是在我们的逻辑索引数组的值为真的索引处选择元素。
逻辑索引数组被称为“掩码”,因为它屏蔽了错误的值。掩码的类型为bool (布尔值)。

与笛卡尔索引的关系:

Indexing by a N-dimensional boolean array is equivalent to indexing by the vector 
of CartesianIndex{N}s where its values are true. 

示例:逻辑掩码的实现

# Create a 2D array of size 5x5
arr = reshape(Vector(1:25), (5, 5))
  
# Apply a logical mask to the array
arr[[true, false, true, false, true], :]

输出:

因此,我们看到如何仅选择索引与掩码[true, false, true, false, true]中的true索引匹配的行。

任何产生布尔值的条件都可以用作掩码。
一维数组示例:

# Create a 1D array of size 10
arr = reshape(Vector(4:2:22), 10)
  
# Create a power of 2 logic mask 
# and map it with the size of arr
mask = map(ispow2, arr)
  
# Apply it to the array
arr[mask]

输出:

二维数组示例:

# Create a 2D array of size 10x10
arr = reshape(Vector(1:100), (10, 10))
  
# Create a prime number logic mask and 
# map it with the size of arr 
# Julia library for working with prime numbers 
using Primes 
mask = map(isprime, arr)
  
# Apply it to the array
arr[mask]

输出:

3D 数组示例:

# Create a 3D array of size 3x2x3
arr = reshape(Vector(2:19), (3, 2, 3))
  
# Create a prime number logic mask 
# and map it with the size of arr
# Julia library for working with prime numbers 
using Primes
mask = map(isprime, arr)
  
# Apply it to the array
arr[mask]

输出:

逻辑索引最常用的情况之一是当我们想要根据多个条件从数组中过滤元素时。
例子:

# Create a 3D array of size 3x2x3
arr = reshape(Vector(2:19), (3, 2, 3))
  
# Create a function that checks for 
# both prime number or power of two
# Julia library for working with prime numbers 
using Primes   
function prime_and_2pow(arr)
    if isprime(arr) || ispow2(arr)
        return true
    else 
        return false
    end
end
  
# Create a logic mask and map it
# with the size of arr
mask = map(prime_and_2pow, arr)
      
# Apply it to the array
arr[mask]

输出: