Iteration utilities
Base.Iterators.Stateful
— TypeStateful(itr)
有几种不同的方式来理解这个迭代器包装器:
- 它提供了一个可变的包装器,围绕一个迭代器及其迭代状态。
- 它将一个类似迭代器的抽象转变为一个类似
Channel
的抽象。 - 它是一个迭代器,在生成一个项目时会变成它自己的剩余迭代器。
Stateful
提供了常规的迭代器接口。像其他可变迭代器(例如 Base.Channel
)一样,如果迭代提前停止(例如在 for
循环中通过 break
),可以通过继续迭代同一个迭代器对象从同一位置恢复迭代(相比之下,一个不可变的迭代器将从头开始)。
示例
julia> a = Iterators.Stateful("abcdef");
julia> isempty(a)
false
julia> popfirst!(a)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> collect(Iterators.take(a, 3))
3-element Vector{Char}:
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
julia> collect(a)
2-element Vector{Char}:
'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)
julia> Iterators.reset!(a); popfirst!(a)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> Iterators.reset!(a, "hello"); popfirst!(a)
'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)
julia> a = Iterators.Stateful([1,1,1,2,3,4]);
julia> for x in a; x == 1 || break; end
julia> peek(a)
3
julia> sum(a) # Sum the remaining elements
7
Base.Iterators.zip
— Functionzip(iters...)
同时运行多个迭代器,直到其中任何一个耗尽。zip
迭代器的值类型是其子迭代器值的元组。
zip
以这样的方式对其子迭代器的调用进行排序,以便状态迭代器在当前迭代中另一个迭代器完成时不会前进。
zip()
没有参数时会产生一个无限的空元组迭代器。
另请参见: enumerate
, Base.splat
.
示例
julia> a = 1:5
1:5
julia> b = ["e","d","b","c","a"]
5-element Vector{String}:
"e"
"d"
"b"
"c"
"a"
julia> c = zip(a,b)
zip(1:5, ["e", "d", "b", "c", "a"])
julia> length(c)
5
julia> first(c)
(1, "e")
Base.Iterators.enumerate
— Functionenumerate(iter)
一个迭代器,生成 (i, x)
,其中 i
是从 1 开始的计数器,x
是来自给定迭代器的第 i
个值。当你不仅需要迭代的值 x
,而且还需要到目前为止的迭代次数时,这非常有用。
请注意,i
可能不适用于索引 iter
,或者可能索引到不同的元素。如果 iter
的索引不是从 1 开始的,或者对于字符串、字典等情况,这种情况可能会发生。如果你想确保 i
是一个索引,请参见 pairs(IndexLinear(), iter)
方法。
示例
julia> a = ["a", "b", "c"];
julia> for (index, value) in enumerate(a)
println("$index $value")
end
1 a
2 b
3 c
julia> str = "naïve";
julia> for (i, val) in enumerate(str)
print("i = ", i, ", val = ", val, ", ")
try @show(str[i]) catch e println(e) end
end
i = 1, val = n, str[i] = 'n'
i = 2, val = a, str[i] = 'a'
i = 3, val = ï, str[i] = 'ï'
i = 4, val = v, StringIndexError("naïve", 4)
i = 5, val = e, str[i] = 'v'
Base.Iterators.rest
— Functionrest(iter, state)
一个迭代器,它产生与 iter
相同的元素,但从给定的 state
开始。
另请参见: Iterators.drop
, Iterators.peel
, Base.rest
.
示例
julia> collect(Iterators.rest([1,2,3,4], 2))
3-element Vector{Int64}:
2
3
4
Base.Iterators.countfrom
— Functioncountfrom(start=1, step=1)
一个从 start
开始并以 step
递增的无限计数迭代器。
示例
julia> for v in Iterators.countfrom(5, 2)
v > 10 && break
println(v)
end
5
7
9
Base.Iterators.take
— Functiontake(iter, n)
一个迭代器,最多生成 iter
的前 n
个元素。
另请参见:drop
, peel
, first
, Base.take!
.
示例
julia> a = 1:2:11
1:2:11
julia> collect(a)
6-element Vector{Int64}:
1
3
5
7
9
11
julia> collect(Iterators.take(a,3))
3-element Vector{Int64}:
1
3
5
Base.Iterators.takewhile
— Functiontakewhile(pred, iter)
一个迭代器,它从 iter
中生成元素,只要谓词 pred
为真,之后将丢弃每个元素。
此函数至少需要 Julia 1.4。
示例
julia> s = collect(1:5)
5-element Vector{Int64}:
1
2
3
4
5
julia> collect(Iterators.takewhile(<(3),s))
2-element Vector{Int64}:
1
2
Base.Iterators.drop
— Functiondrop(iter, n)
一个生成 iter
中除前 n
个元素外所有元素的迭代器。
示例
julia> a = 1:2:11
1:2:11
julia> collect(a)
6-element Vector{Int64}:
1
3
5
7
9
11
julia> collect(Iterators.drop(a,4))
2-element Vector{Int64}:
9
11
Base.Iterators.dropwhile
— Functiondropwhile(pred, iter)
一个迭代器,它会从 iter
中丢弃元素,只要谓词 pred
为真,之后返回每个元素。
此函数至少需要 Julia 1.4。
示例
julia> s = collect(1:5)
5-element Vector{Int64}:
1
2
3
4
5
julia> collect(Iterators.dropwhile(<(3),s))
3-element Vector{Int64}:
3
4
5
Base.Iterators.cycle
— Functioncycle(iter[, n::Int])
一个无限循环遍历 iter
的迭代器。如果指定了 n
,则循环遍历 iter
该次数。当 iter
为空时,cycle(iter)
和 cycle(iter, n)
也为空。
Iterators.cycle(iter, n)
是 Base.repeat
(vector, n)
的惰性等价,而 Iterators.repeated
(iter, n)
是惰性 Base.fill
(item, n)
。
方法 cycle(iter, n)
在 Julia 1.11 中添加。
示例
julia> for (i, v) in enumerate(Iterators.cycle("hello"))
print(v)
i > 10 && break
end
hellohelloh
julia> foreach(print, Iterators.cycle(['j', 'u', 'l', 'i', 'a'], 3))
juliajuliajulia
julia> repeat([1,2,3], 4) == collect(Iterators.cycle([1,2,3], 4))
true
julia> fill([1,2,3], 4) == collect(Iterators.repeated([1,2,3], 4))
true
Base.Iterators.repeated
— Functionrepeated(x[, n::Int])
一个生成值 x
的迭代器,永远生成。如果指定了 n
,则生成 x
这么多次(等价于 take(repeated(x), n)
)。
另请参见 fill
,并比较 Iterators.cycle
。
示例
julia> a = Iterators.repeated([1 2], 4);
julia> collect(a)
4-element Vector{Matrix{Int64}}:
[1 2]
[1 2]
[1 2]
[1 2]
julia> ans == fill([1 2], 4)
true
julia> Iterators.cycle([1 2], 4) |> collect |> println
[1, 2, 1, 2, 1, 2, 1, 2]
Base.Iterators.product
— Functionproduct(iters...)
返回一个迭代器,该迭代器生成多个迭代器的乘积。每个生成的元素都是一个元组,其第 i
个元素来自第 i
个参数迭代器。第一个迭代器变化最快。
另请参见: zip
, Iterators.flatten
.
示例
julia> collect(Iterators.product(1:2, 3:5))
2×3 Matrix{Tuple{Int64, Int64}}:
(1, 3) (1, 4) (1, 5)
(2, 3) (2, 4) (2, 5)
julia> ans == [(x,y) for x in 1:2, y in 3:5] # 收集一个涉及 Iterators.product 的生成器
true
Base.Iterators.flatten
— Functionflatten(iter)
给定一个返回迭代器的迭代器,返回一个返回这些迭代器元素的迭代器。换句话说,参数迭代器的元素被连接在一起。
示例
julia> collect(Iterators.flatten((1:2, 8:9)))
4-element Vector{Int64}:
1
2
8
9
julia> [(x,y) for x in 0:1 for y in 'a':'c'] # 收集涉及 Iterators.flatten 的生成器
6-element Vector{Tuple{Int64, Char}}:
(0, 'a')
(0, 'b')
(0, 'c')
(1, 'a')
(1, 'b')
(1, 'c')
Base.Iterators.flatmap
— FunctionIterators.flatmap(f, iterators...)
等价于 flatten(map(f, iterators...))
。
另见 Iterators.flatten
, Iterators.map
。
此函数在 Julia 1.9 中添加。
示例
julia> Iterators.flatmap(n -> -n:2:n, 1:3) |> collect
9-element Vector{Int64}:
-1
1
-2
0
2
-3
-1
1
3
julia> stack(n -> -n:2:n, 1:3)
ERROR: DimensionMismatch: stack expects uniform slices, got axes(x) == (1:3,) while first had (1:2,)
[...]
julia> Iterators.flatmap(n -> (-n, 10n), 1:2) |> collect
4-element Vector{Int64}:
-1
10
-2
20
julia> ans == vec(stack(n -> (-n, 10n), 1:2))
true
Base.Iterators.partition
— Functionpartition(collection, n)
每次迭代 n
个元素的集合。
示例
julia> collect(Iterators.partition([1,2,3,4,5], 2))
3-element Vector{SubArray{Int64, 1, Vector{Int64}, Tuple{UnitRange{Int64}}, true}}:
[1, 2]
[3, 4]
[5]
Base.Iterators.map
— FunctionIterators.map(f, iterators...)
创建一个惰性映射。这是写成 (f(args...) for args in zip(iterators...))
的另一种语法。
此函数至少需要 Julia 1.6。
示例
julia> collect(Iterators.map(x -> x^2, 1:3))
3-element Vector{Int64}:
1
4
9
Base.Iterators.filter
— FunctionIterators.filter(flt, itr)
给定一个谓词函数 flt
和一个可迭代对象 itr
,返回一个可迭代对象,该对象在迭代时产生满足 flt(x)
的 itr
的元素 x
。原始迭代器的顺序得以保留。
此函数是 惰性 的;也就是说,它保证在 $Θ(1)$ 时间内返回并使用 $Θ(1)$ 的额外空间,并且 flt
不会在调用 filter
时被调用。对 flt
的调用将在迭代返回的可迭代对象时进行。这些调用不会被缓存,并且在重新迭代时会进行重复调用。
对从 filter
返回的迭代器进行后续 惰性 转换,例如 Iterators.reverse
或 cycle
,也会延迟对 flt
的调用,直到收集或迭代返回的可迭代对象。如果过滤谓词是非确定性的,或者其返回值依赖于对 itr
的元素的迭代顺序,则与惰性转换的组合可能会导致意外的行为。如果这不可取,请确保 flt
是一个纯函数,或者在进一步转换之前收集中间的 filter
迭代器。
请参见 Base.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> foreach(println, f)
1
3
5
julia> [x for x in [1, 2, 3, 4, 5] if isodd(x)] # 收集一个基于 Iterators.filter 的生成器
3-element Vector{Int64}:
1
3
5
Base.Iterators.accumulate
— FunctionIterators.accumulate(f, itr; [init])
给定一个具有两个参数的函数 f
和一个迭代器 itr
,返回一个新的迭代器,该迭代器依次将 f
应用到前一个值和 itr
的下一个元素。
这实际上是 Base.accumulate
的惰性版本。
关键字参数 init
在 Julia 1.5 中添加。
示例
julia> a = Iterators.accumulate(+, [1,2,3,4]);
julia> foreach(println, a)
1
3
6
10
julia> b = Iterators.accumulate(/, (2, 5, 2, 5); init = 100);
julia> collect(b)
4-element Vector{Float64}:
50.0
10.0
5.0
1.0
Base.Iterators.reverse
— FunctionIterators.reverse(itr)
给定一个迭代器 itr
,则 reverse(itr)
是一个遍历相同集合但顺序相反的迭代器。这个迭代器是“惰性”的,因为它不会复制集合以进行反转;请参见 Base.reverse
以获取急切实现。
(默认情况下,这将返回一个包装 itr
的 Iterators.Reverse
对象,如果相应的 iterate
方法已定义,则该对象是可迭代的,但某些 itr
类型可能实现了更专业的 Iterators.reverse
行为。)
并非所有迭代器类型 T
都支持反向迭代。如果 T
不支持,则对 Iterators.reverse(itr::T)
进行迭代将抛出 MethodError
,因为缺少 Iterators.Reverse{T}
的 iterate
方法。(要实现这些方法,可以通过 r.itr
从 r::Iterators.Reverse{T}
对象中获取原始迭代器 itr::T
;更一般地,可以使用 Iterators.reverse(r)
。)
示例
julia> foreach(println, Iterators.reverse(1:5))
5
4
3
2
1
Base.Iterators.only
— Functiononly(x)
返回集合 x
的唯一元素,如果集合包含零个或多个元素,则抛出 ArgumentError
。
此方法至少需要 Julia 1.4。
示例
julia> only(["a"])
"a"
julia> only("a")
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> only(())
ERROR: ArgumentError: Tuple contains 0 elements, must contain exactly 1 element
Stacktrace:
[...]
julia> only(('a', 'b'))
ERROR: ArgumentError: Tuple contains 2 elements, must contain exactly 1 element
Stacktrace:
[...]
Base.Iterators.peel
— Functionpeel(iter)
返回第一个元素和一个迭代器,用于遍历其余元素。
如果迭代器为空,则返回 nothing
(类似于 iterate
)。
先前版本在迭代器为空时会抛出 BoundsError。
另请参见: Iterators.drop
, Iterators.take
.
示例
julia> (a, rest) = Iterators.peel("abc");
julia> a
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> collect(rest)
2-element Vector{Char}:
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)