Julia:为什么需要在重塑数组后收集输出?
Julia: Why is it necessary to collect the output after reshaping an Array?
A = collect(reshape(1:16, 4, 4))
4×4 Array{Int64,2}:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
怎么有必要collect
?不能reshape
自动输出一个4x4 Array{Int64, 2}
?在哪些情况下我需要 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}
?
这里的关键是 reshape
通常提供对原始数据结构的 视图 ……它只是将您查看该数据的方式改变为新的形状。在这种情况下,您的原始数据结构只是范围 1:16
.
范围是非常紧凑和高效的类似数组的对象。他们不需要存储所有元素;相反,他们只是做基本的数学运算来动态计算每个元素。通过这种方式,它们实际上 比 Array
等价物(如 collect(1:16)
)快 。在大多数情况下,您可以在 Array
工作的任何地方使用范围。这是为什么你不应该在函数签名中指定 arg::Array
或 ::Matrix
的主要原因——相反你(和其他库作者)应该使用 ::AbstractArray
和 ::AbstractMatrix
如果你不需要内存中的表示。
有两个主要例外:范围是完全不可变的——您不能赋值或修改它们的任何元素。所以这就是为什么您可能想要 collect
变成 Array
的原因之一。另一种情况是,如果您正在调用不支持 Julia 的通用灵活性的 C/Fortran/external 库。在这些情况下,他们通常需要像 Array
.
这样的内存表示
reshape(1:16, 4, 4)
也是如此。类似于范围如何即时计算它们的元素,在这种情况下,ReshapedArray
将您传递给它的索引转换回原始数组 (1:16
) 的原始形状,然后它访问那个原始数组。它非常有效地做到这一点。事实上,如果你在幕后偷看,你会发现它只存储了 4 个整数:
julia> dump(reshape(1:16, 4, 4))
Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}
parent: UnitRange{Int64}
start: Int64 1
stop: Int64 16
dims: Tuple{Int64,Int64}
1: Int64 4
2: Int64 4
mi: Tuple{} ()
它只需要知道 UnitRange
父级 (1-16) 的起点和终点,以及它重塑为 (4x4) 的尺寸。其他一切都是按需完成的。正如您将注意到的,这里的大小无关紧要 — reshape(a:b, y, z)
将始终只存储 4 个整数,无论 a:b
有多大。
A = collect(reshape(1:16, 4, 4))
4×4 Array{Int64,2}:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
怎么有必要collect
?不能reshape
自动输出一个4x4 Array{Int64, 2}
?在哪些情况下我需要 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}
?
这里的关键是 reshape
通常提供对原始数据结构的 视图 ……它只是将您查看该数据的方式改变为新的形状。在这种情况下,您的原始数据结构只是范围 1:16
.
范围是非常紧凑和高效的类似数组的对象。他们不需要存储所有元素;相反,他们只是做基本的数学运算来动态计算每个元素。通过这种方式,它们实际上 比 Array
等价物(如 collect(1:16)
)快 。在大多数情况下,您可以在 Array
工作的任何地方使用范围。这是为什么你不应该在函数签名中指定 arg::Array
或 ::Matrix
的主要原因——相反你(和其他库作者)应该使用 ::AbstractArray
和 ::AbstractMatrix
如果你不需要内存中的表示。
有两个主要例外:范围是完全不可变的——您不能赋值或修改它们的任何元素。所以这就是为什么您可能想要 collect
变成 Array
的原因之一。另一种情况是,如果您正在调用不支持 Julia 的通用灵活性的 C/Fortran/external 库。在这些情况下,他们通常需要像 Array
.
reshape(1:16, 4, 4)
也是如此。类似于范围如何即时计算它们的元素,在这种情况下,ReshapedArray
将您传递给它的索引转换回原始数组 (1:16
) 的原始形状,然后它访问那个原始数组。它非常有效地做到这一点。事实上,如果你在幕后偷看,你会发现它只存储了 4 个整数:
julia> dump(reshape(1:16, 4, 4))
Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}
parent: UnitRange{Int64}
start: Int64 1
stop: Int64 16
dims: Tuple{Int64,Int64}
1: Int64 4
2: Int64 4
mi: Tuple{} ()
它只需要知道 UnitRange
父级 (1-16) 的起点和终点,以及它重塑为 (4x4) 的尺寸。其他一切都是按需完成的。正如您将注意到的,这里的大小无关紧要 — reshape(a:b, y, z)
将始终只存储 4 个整数,无论 a:b
有多大。