遍历与迭代器

迭代器

Base.Iterators 模块提供了一系列为 for ... in 准备的、用于更方便地控制遍历的工具。

eachindex 通常用于得到数组索引的合适遍历工具。它比使用 1:length(A) 兼容性更强,因为 1:length(A) 不适用于多维数组、数组 view 及其它包可能出现的数组(如索引不从 1 开始的数组)。

julia> A = [10 20; 30 40];
julia> for i in eachindex(A) println("A[", i, "] == ", A[i]) endA[1] == 10 A[2] == 30 A[3] == 20 A[4] == 40

使用 enumerate 遍历物品时,得到的值是一对 (i, v),其中 i 是从 1 开始的计数器,v 是正常遍历物品得到的值。

julia> a = ["a", "b", "c"];
julia> for (index, balue) in enumerate(a) println("a[$index] = $value") endERROR: UndefVarError: `value` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> for (index, value) in enumerate(a) println("a[$index] = $value") enda[1] = a a[2] = b a[3] = c

zip 可用于合并多个可遍历的物品,一直遍历直到其中一个到达末尾。

julia> z = zip(1:3, "abcde")zip(1:3, "abcde")
julia> length(z)3
julia> first(z)(1, 'a')
julia> collect(z)3-element Vector{Tuple{Int64, Char}}: (1, 'a') (2, 'b') (3, 'c')

filter 用于生成满足特定要求的迭代器,需注意在使用时不与导出的另一个 filter 混淆

julia> f = Iterators.filter(isodd, [1, 2, 3, 4, 5])Base.Iterators.Filter{typeof(isodd), Vector{Int64}}(isodd, [1, 2, 3, 4, 5])
julia> collect(f)3-element Vector{Int64}: 1 3 5

自定义

Julia 允许用户给自定义类型实现迭代方式。

这需要定义 iterate 函数的两个方法

在进行 for ... in 循环时,

for item in iter   # 或 "for item = iter"
    # body
end

以上代码被解释为[1]

next = iterate(iter)
while next !== nothing
    (item, state) = next
    # body
    next = iterate(iter, state)
end

这是一个自定义的样例:

julia> struct n3
           v::Int
       end
julia> function Base.iterate(i::n3, n::Int=i.v) # 第一次调用时不会有第二个参数 if n == 1 return nothing # 表示结束 end v= n&1==0 ? n>>1 : n*3+1 return (v, v) # (返回值, 下一个状态) end
julia> for i in n3(10) println(i, ' ') end5 16 8 4 2 1
julia> [n3(27)...]111-element Vector{Int64}: 82 41 124 62 31 94 47 142 71 214 ⋮ 40 20 10 5 16 8 4 2 1
  • 1https://docs.juliacn.com/latest/manual/interfaces