Julia 中的逻辑和笛卡尔索引
与大多数技术计算语言一样,Julia 提供了一流的数组实现,其中包含非常重要的函数,使处理 N 维数组变得非常容易。最新功能之一,基于点(。)的广播使大多数“重复”数组操作成为单行代码。
数组索引
在 Julia 中对数组进行索引与它的对应项类似。
句法:
x = arr[index_1, index_2, …, index_n]
where each index_k may be a scalar integer, an array of integers, or an object that represents an array of scalar indices.
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 数组的基于数组的 CartesianIndexing:
# 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 数组的基于数组的 CartesianIndexing:
# 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与笛卡尔坐标非常相似,并且以类似的方式函数。
例子:
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]
输出: