📜  在 Julia 中创建父数组的视图 – view()、@view 和 @views 方法(1)

📅  最后修改于: 2023-12-03 15:07:41.763000             🧑  作者: Mango

在 Julia 中创建父数组的视图 – view()、@view 和 @views 方法

在 Julia 中,我们经常需要对数组进行操作。但是,有时我们需要从原始数组中提取一个子集,同时不必复制原始数组的内容。在这种情况下,我们可以使用视图(view)来实现这个目标。视图是一种轻量级的对象,它只存储原始数组的指针和一些计算索引的信息。这个指针指向原始数组在内存中的位置,因此,当我们对视图进行操作时,它会直接反映在原始数组中。

Julia 提供了 3 种方法来创建数组的视图:view()@view@views。这些方法可以帮助我们在不复制底层数组的情况下,高效地创建和操作数组的子集。

使用 view() 方法

view() 是 Julia 内置的一个方法,它可以创建一个数组的视图。view() 方法的语法如下:

view(A, inds...)

其中,A 表示底层数组,inds... 表示一组索引,用于创建视图。这个索引对于底层数组 A 和视图 v 来说都是相同的。

下面是一个例子,我们将创建一个数组 A,并使用 view() 方法创建一个视图 v

julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> v = view(A, 1:2, 1:2)
2×2 view(::Array{Int64,2}, 1:2, 1:2) with eltype Int64:
 1  2
 4  5

在这个例子中,我们使用了 view() 方法来创建一个 2×2 的视图。这个视图包含 A 的前两行和前两列,原始数组 A 并没有被复制。

我们可以看到,视图的类型是 view(::Array{Int64, 2}, 1:2, 1:2),其中 ::Array{Int64, 2} 表示它是一个 2 维的整数数组,并且它是一个 2×2 的视图,对应于底层数组的前两行和前两列。

我们可以对视图 v 进行操作,这些操作会反映到原始数组 A 中。

julia> v[1, 1] = 10
10

julia> A
3×3 Array{Int64,2}:
 10  2  3
  4  5  6
  7  8  9

在这个例子中,我们将视图 v 的第一个元素设置为 10。我们可以看到,原始数组 A 中的第一个元素也变成了 10。

注意,尽管视图只包含原始数组的一部分,但是视图和原始数组都指向同一段内存,因此,对视图的操作会直接反映在原始数组中。这使得视图非常高效,因为我们不需要复制整个原始数组。

使用 @view 宏

除了 view() 方法之外,Julia 还为创建视图提供了一个 @view 宏。这个宏的语法与 view() 方法非常相似,但是使用方式略有不同。

下面是一个使用 @view 宏创建视图的例子:

julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> v = @view A[1:2, 1:2]
2×2 view(::Array{Int64,2}, 1:2, 1:2) with eltype Int64:
 1  2
 4  5

通过使用 @view 宏,我们可以将语法写成类似于对数组进行索引的方式。与 view() 方法一样,@view 宏创建的视图也是非常高效的,因为它不会复制底层数组的内容。

使用 @views 宏

最后,Julia 还提供了一个 @views 宏,它可以帮助我们将某些操作视图化。具体来说,我们可以使用 @views 宏来创建一系列视图,并对这些视图进行操作,而不必显式地创建每个视图。

下面是一个使用 @views 宏创建视图的例子:

julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> @views [A[1:2, 1:2] A[1:2, 2:3]; A[2:3, 1:2] A[2:3, 2:3]] .= 0
3×3 Array{Int64,2}:
 0  0  0
 0  0  0
 0  0  0

在这个例子中,我们使用了 @views 宏来创建 4 个视图,并将它们排列在一个 2×2 的矩阵中。我们在这些视图上执行了一个操作,将它们的值设置为 0。使用 @views 宏,我们可以轻松地将这些视图组合在一起,并且可以省去创建每个视图的步骤。

结论

视图是一个非常强大的功能,可以帮助我们轻松地操作底层数组的子集,同时避免了复制大量数据的开销。在 Julia 中,我们可以使用 view()@view@views 方法来创建视图。如果我们希望使用视图来执行一系列操作,那么 @views 宏是一个十分方便的工具。