DNF*_*DNF 8 iteration julia reverse-iterator
昨天我有机会以相反的顺序迭代一个集合.我发现了这个reverse函数,但这并没有返回迭代器,但实际上创建了一个反向集合.
显然,曾经有一个Reverse迭代器,几年前被删除了.我也可以找到被称为某种东西(类型?)的引用Order.Reverse,但这似乎不适用于我的问题.
该Iterators.jl包具有许多有趣的迭代模式,但显然不是反向迭代.
我当然可以使用该reverse函数,在某些情况下,例如reverse(eachindex(c)),它返回一个反向迭代器,但我更喜欢一般的反向迭代器.
有这样的事吗?
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}})
Run Code Online (Sandbox Code Playgroud)
请注意,这仅适用于具有特定定义的反向迭代的类型.也就是说,他们已经明确定义Base.iterate(::Iterators.Reverse{T}, ...)了T是自定义类型的位置.所以它不是完全通用的(由于下面记录的原因),但它确实适用于支持它的任何类型.
原始答案
杰夫在三年前删除逆向迭代器时的评论(在你链接的问题中)今天同样如此:
我非常赞成删除它,因为它根本不起作用.与iterator.jl中的其他内容不同,它依赖于索引,而不是迭代,甚至不能处理可索引的所有内容(例如UTF8String).我讨厌在Base有像这样的地雷.
在最基本的层面上,迭代器只知道如何做三件事:开始迭代,获取下一个元素,并检查迭代是否完成.为了创建一个不使用这些原语分配的迭代器,你需要一个O(n ^ 2)算法:遍历整个迭代器,随时计算,直到找到最后一个元素.然后再次走迭代器,这次只停留在倒数第二个元素处.当然这不分配,但它会是这样不仅仅是收集迭代器到一个数组,然后向后索引慢.对于一次性迭代器(如eachline),它将完全被破坏.因此,根本不可能创建一个有效的通用反向迭代器.
请注意,reverse(eachindex(c))一般不起作用:
julia> reverse(eachindex(sprand(5,5,.2)))
ERROR: MethodError: no method matching reverse(::CartesianRange{CartesianIndex{2}})
Run Code Online (Sandbox Code Playgroud)
一种仍然适用于偏移数组的替代方案是reverse(linearindices(c)).