遍历与迭代器
迭代器
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])
end
A[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")
end
ERROR: UndefVarError: `value` not defined in `Main`
Suggestion: check for spelling errors or missing imports.
Stacktrace:
[1] top-level scope
@ .\REPL[30]:2
julia> for (index, value) in enumerate(a)
println("a[$index] = $value")
end
a[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
这是一个自定义的样例:
struct n3
v::Int
end
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, ' ')
end
5
16
8
4
2
1
julia> [n3(27)...]
111-element Vector{Int64}:
82
41
124
62
31
94
47
142
71
214
107
322
161
⋮
53
160
80
40
20
10
5
16
8
4
2
1
- 1
https://docs.juliacn.com/latest/manual/interfaces