Iteration utilities

Base.Iterators.StatefulType
Stateful(itr)

Существует несколько различных способов рассмотреть эту обертку итератора:

  1. Она предоставляет изменяемую обертку вокруг итератора и его состояния итерации.
  2. Она превращает абстракцию, похожую на итератор, в абстракцию, похожую на Channel.
  3. Это итератор, который изменяется, чтобы стать своим собственным итератором остатка, когда элемент производится.

Stateful предоставляет обычный интерфейс итератора. Как и другие изменяемые итераторы (например, Base.Channel), если итерация прерывается преждевременно (например, с помощью break в цикле for), итерация может быть возобновлена с того же места, продолжая итерацию по тому же объекту итератора (в отличие от неизменяемого итератора, который бы начал с самого начала).

Примеры

julia> a = Iterators.Stateful("abcdef");

julia> isempty(a)
false

julia> popfirst!(a)
'a': ASCII/Unicode U+0061 (категория Ll: буква, строчная)

julia> collect(Iterators.take(a, 3))
3-element Vector{Char}:
 'b': ASCII/Unicode U+0062 (категория Ll: буква, строчная)
 'c': ASCII/Unicode U+0063 (категория Ll: буква, строчная)
 'd': ASCII/Unicode U+0064 (категория Ll: буква, строчная)

julia> collect(a)
2-element Vector{Char}:
 'e': ASCII/Unicode U+0065 (категория Ll: буква, строчная)
 'f': ASCII/Unicode U+0066 (категория Ll: буква, строчная)

julia> Iterators.reset!(a); popfirst!(a)
'a': ASCII/Unicode U+0061 (категория Ll: буква, строчная)

julia> Iterators.reset!(a, "hello"); popfirst!(a)
'h': ASCII/Unicode U+0068 (категория Ll: буква, строчная)
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) # Сумма оставшихся элементов
7
source
Base.Iterators.zipFunction
zip(iters...)

Запускает несколько итераторов одновременно, пока один из них не исчерпается. Тип значения итератора zip — это кортеж значений его подитераторов.

Note

zip упорядочивает вызовы своих подитераторов таким образом, что состояния итераторов не будут продвигаться, когда другой итератор завершает работу в текущей итерации.

Note

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")
source
Base.Iterators.enumerateFunction
enumerate(iter)

Итератор, который возвращает (i, x), где i — это счетчик, начинающийся с 1, а x — это i-е значение из данного итератора. Это полезно, когда вам нужны не только значения x, по которым вы итерируете, но и количество итераций на данный момент.

Обратите внимание, что i может быть недействительным для индексации iter или может индексировать другой элемент. Это произойдет, если iter имеет индексы, которые не начинаются с 1, и может произойти для строк, словарей и т. д. См. метод pairs(IndexLinear(), iter), если вы хотите убедиться, что i является индексом.

Примеры

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'
source
Base.Iterators.restFunction
rest(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
source
Base.Iterators.countfromFunction
countfrom(start=1, step=1)

Итератор, который считает бесконечно, начиная с start и увеличивая на step.

Примеры

julia> for v in Iterators.countfrom(5, 2)
           v > 10 && break
           println(v)
       end
5
7
9
source
Base.Iterators.takeFunction
take(iter, n)

Итератор, который генерирует не более первых n элементов iter.

См. также: 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
source
Base.Iterators.takewhileFunction
takewhile(pred, iter)

Итератор, который генерирует элементы из iter, пока предикат pred истинный, после чего отбрасывает все элементы.

Julia 1.4

Эта функция требует как минимум 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
source
Base.Iterators.dropFunction
drop(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
source
Base.Iterators.dropwhileFunction
dropwhile(pred, iter)

Итератор, который отбрасывает элементы из iter, пока предикат pred истинен, после чего возвращает каждый элемент.

Julia 1.4

Эта функция требует как минимум 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
source
Base.Iterators.cycleFunction
cycle(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).

Julia 1.11

Метод 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
source
Base.Iterators.repeatedFunction
repeated(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]
source
Base.Iterators.productFunction
product(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
source
Base.Iterators.flattenFunction
flatten(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')
source
Base.Iterators.flatmapFunction
Iterators.flatmap(f, iterators...)

Эквивалентно flatten(map(f, iterators...)).

См. также Iterators.flatten, Iterators.map.

Julia 1.9

Эта функция была добавлена в 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
source
Base.Iterators.partitionFunction
partition(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]
source
Base.Iterators.mapFunction
Iterators.map(f, iterators...)

Создает ленивое отображение. Это другой синтаксис для записи (f(args...) for args in zip(iterators...)).

Julia 1.6

Эта функция требует как минимум Julia 1.6.

Примеры

julia> collect(Iterators.map(x -> x^2, 1:3))
3-element Vector{Int64}:
 1
 4
 9
source
Base.Iterators.filterFunction
Iterators.filter(flt, itr)

Данная функция принимает предикат flt и итерируемый объект itr, возвращая итерируемый объект, который при итерации выдает элементы x из itr, удовлетворяющие условию flt(x). Порядок оригинального итератора сохраняется.

Эта функция ленивая; то есть, она гарантированно возвращает результат за $Θ(1)$ время и использует $Θ(1)$ дополнительного пространства, а flt не будет вызвана при вызове filter. Вызовы к flt будут производиться при итерации по возвращаемому итерируемому объекту. Эти вызовы не кэшируются, и повторные вызовы будут производиться при повторной итерации.

Warning

Последующие ленивые преобразования итератора, возвращаемого из 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
source
Base.Iterators.accumulateFunction
Iterators.accumulate(f, itr; [init])

Данная функция принимает функцию с 2 аргументами f и итератор itr, возвращает новый итератор, который последовательно применяет f к предыдущему значению и следующему элементу itr.

Это фактически ленивый вариант Base.accumulate.

Julia 1.5

Ключевой аргумент 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
source
Base.Iterators.reverseFunction
Iterators.reverse(itr)

Данный итератор itr, тогда reverse(itr) является итератором по той же коллекции, но в обратном порядке. Этот итератор "ленивый" в том смысле, что он не создает копию коллекции для ее реверсирования; см. Base.reverse для жадной реализации.

(По умолчанию это возвращает объект Iterators.Reverse, оборачивающий itr, который можно перебирать, если соответствующие методы iterate определены, но некоторые типы itr могут реализовывать более специализированные поведения Iterators.reverse.)

Не все типы итераторов T поддерживают итерацию в обратном порядке. Если T этого не поддерживает, то перебор Iterators.reverse(itr::T) вызовет MethodError из-за отсутствующих методов iterate для Iterators.Reverse{T}. (Чтобы реализовать эти методы, оригинальный итератор itr::T можно получить из объекта r::Iterators.Reverse{T} с помощью r.itr; более общим образом, можно использовать Iterators.reverse(r).)

Примеры

julia> foreach(println, Iterators.reverse(1:5))
5
4
3
2
1
source
Base.Iterators.onlyFunction
only(x)

Возвращает единственный элемент коллекции x или выбрасывает ArgumentError, если коллекция содержит ноль или несколько элементов.

См. также first, last.

Julia 1.4

Этот метод требует как минимум Julia 1.4.

Примеры

julia> only(["a"])
"a"

julia> only("a")
'a': ASCII/Unicode U+0061 (категория Ll: буква, строчная)

julia> only(())
ERROR: ArgumentError: Кортеж содержит 0 элементов, должен содержать ровно 1 элемент
Stacktrace:
[...]

julia> only(('a', 'b'))
ERROR: ArgumentError: Кортеж содержит 2 элемента, должен содержать ровно 1 элемент
Stacktrace:
[...]
source
Base.Iterators.peelFunction
peel(iter)

Возвращает первый элемент и итератор по оставшимся элементам.

Если итератор пуст, возвращает nothing (как iterate).

Julia 1.7

Предыдущие версии выбрасывают BoundsError, если итератор пуст.

См. также: Iterators.drop, Iterators.take.

Примеры

julia> (a, rest) = Iterators.peel("abc");

julia> a
'a': ASCII/Unicode U+0061 (категория Ll: Буква, строчная)

julia> collect(rest)
2-element Vector{Char}:
 'b': ASCII/Unicode U+0062 (категория Ll: Буква, строчная)
 'c': ASCII/Unicode U+0063 (категория Ll: Буква, строчная)
source