【问题标题】:Reverse iteration in JuliaJulia中的反向迭代
【发布时间】:2017-07-31 11:45:44
【问题描述】:

昨天我有机会想以相反的顺序迭代一个集合。我找到了reverse 函数,但这并没有返回迭代器,而是实际上创建了一个反向集合。

显然,曾经有一个Reverse 迭代器,几年前是removed。我还可以找到 reference 到名为 Order.Reverse 的东西(一种类型?),但这似乎不适用于我的问题。

Iterators.jl 包有许多有趣的迭代模式,但显然没有反向迭代。

我当然可以使用reverse 函数,在某些情况下,例如reverse(eachindex(c)),它返回一个反向迭代器,但我更喜欢通用反向迭代器。

有这种事吗?

【问题讨论】:

    标签: iteration julia reverse-iterator


    【解决方案1】:

    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 删除反向迭代器时的评论(在 the issue you linked 中)与今天同样重要:

    我非常赞成删除它,因为它根本不起作用。与 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)) 仍然适用于偏移数组的另一种选择。

    【讨论】:

    • 确实阅读了该评论,但我并不认为它意味着反向迭代是不可行的。 Stefan Karpinski 的以下评论也没有给人留下这种印象。无论如何,您的论点很有意义,但是支持某些集合子集的反向迭代是否不切实际?我看到 Python 确实有类似的东西:docs.python.org/3/library/functions.html#reversed
    • 不,这根本不是不切实际的。只是还没有人定义过这样的接口——我们只需要有人来做这项工作,我觉得它会被接受。参考。 github.com/JuliaLang/julia/issues/4590#issuecomment-26684029
    • 我明白了。嗯,这回答了我的问题。
    猜你喜欢
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多