更新 Julia 1.0+
您现在可以使用Iterators.reverse
来反转有限的类型子集。例如:
julia> Iterators.reverse(1:10)
10:-1:1
julia> Iterators.reverse(CartesianIndices(zeros(2,3))) |> collect
2×3 Array{CartesianIndex{2},2}:
CartesianIndex(2, 3) CartesianIndex(2, 2) CartesianIndex(2, 1)
CartesianIndex(1, 3) CartesianIndex(1, 2) CartesianIndex(1, 1)
julia> Iterators.Reverse([1,1,2,3,5]) |> collect
5-element Array{Int64,1}:
5
3
2
1
1
# But not all iterables support it (and new iterables don't support it by default):
julia> Iterators.reverse(Set(1:2)) |> collect
ERROR: MethodError: no method matching iterate(::Base.Iterators.Reverse{Set{Int64}})
请注意,这仅适用于已明确定义反向迭代的类型。也就是说,他们已经明确定义Base.iterate(::Iterators.Reverse{T}, ...)
了哪里 T 是自定义类型。所以它不是完全通用的(出于下面记录的原因),但它确实适用于任何支持它的类型。
原始答案
Jeff 在三年前(在您链接的问题中)删除反向迭代器时的评论与今天同样重要:
我非常赞成删除它,因为它根本不起作用。与 iterator.jl 中的所有其他内容不同,它依赖于索引,而不是迭代,甚至不适用于可索引的所有内容(例如 UTF8String)。我讨厌在基地有这样的地雷。
在最基本的层面上,迭代器只知道如何做三件事:开始迭代,获取下一个元素,检查迭代是否完成。为了创建一个不使用这些原语进行分配的迭代器,您需要一个 O(n^2) 算法:遍历整个迭代器,边走边算,直到找到最后一个元素。然后再次遍历迭代器,只是这次停在倒数第二个元素处。当然它不会分配,但它会比将迭代器收集到一个数组中然后向后索引要慢得多。对于一次性迭代器(如eachline
),它将完全被破坏。所以根本不可能创建一个高效的通用反向迭代器。
请注意,这reverse(eachindex(c))
通常不起作用:
julia> reverse(eachindex(sprand(5,5,.2)))
ERROR: MethodError: no method matching reverse(::CartesianRange{CartesianIndex{2}})
仍然适用于偏移数组的一种替代方法是reverse(linearindices(c))
.