Introduction

# IterTools

## Installation

Install this package with `Pkg.add("IterTools")`

# Usage

## distinct(xs)

Iterate through values skipping over those already encountered.

``distinct(xs)``

Iterate through values skipping over those already encountered.

``````julia> for i in distinct([1,1,2,1,2,4,1,2,3,4])
@show i
end
i = 1
i = 2
i = 4
i = 3``````
source

## firstrest(xs)

Return first element and `Iterators.rest` iterator as a tuple.

``firstrest(xs) -> (f, r)``

Return the first element and an iterator of the rest as a tuple.

``````julia> f, r = firstrest(1:3)
(1, Base.Iterators.Rest{UnitRange{Int64},Int64}(1:3, 1))

julia> collect(r)
2-element Array{Int64,1}:
2
3``````
source

## groupby(f, xs)

Group consecutive values that share the same result of applying `f`.

``groupby(f, xs)``

Group consecutive values that share the same result of applying `f`.

``````julia> for i in groupby(x -> x, ["face", "foo", "bar", "book", "baz", "zzz"])
@show i
end
i = ["face", "foo"]
i = ["bar", "book", "baz"]
i = ["zzz"]``````
source

## imap(f, xs1, [xs2, ...])

Iterate over values of a function applied to successive values from one or more iterators.

``imap(f, xs1, [xs2, ...])``

Iterate over values of a function applied to successive values from one or more iterators. Like `Iterators.zip`, the iterator is done when any of the input iterators have been exhausted.

``````julia> for i in imap(+, [1,2,3], [4,5,6])
@show i
end
i = 5
i = 7
i = 9``````
source

## iterated(f, x)

Iterate over successive applications of `f`, as in `x, f(x), f(f(x)), f(f(f(x))), ...`.

``iterated(f, x)``

Iterate over successive applications of `f`, as in `x`, `f(x)`, `f(f(x))`, `f(f(f(x)))`, ...

Use `Base.Iterators.take()` to obtain the required number of elements.

``````julia> for i in Iterators.take(iterated(x -> 2x, 1), 5)
@show i
end
i = 1
i = 2
i = 4
i = 8
i = 16

julia> for i in Iterators.take(iterated(sqrt, 100), 6)
@show i
end
i = 100
i = 10.0
i = 3.1622776601683795
i = 1.7782794100389228
i = 1.333521432163324
i = 1.1547819846894583``````
source

## ncycle(xs, n)

Cycles through an iterator `n` times.

``ncycle(iter, n)``

Cycle through `iter` `n` times.

``````julia> for i in ncycle(1:3, 2)
@show i
end
i = 1
i = 2
i = 3
i = 1
i = 2
i = 3``````
source

## nth(xs, n)

Return the `n`th element of `xs`.

``nth(xs, n)``

Return the `n`th element of `xs`. This is mostly useful for non-indexable collections.

``````julia> mersenne = Set([3, 7, 31, 127])
Set([7, 31, 3, 127])

julia> nth(mersenne, 3)
3``````
source

## partition(xs, n, [step])

Group values into `n`-tuples.

``partition(xs, n, [step])``

Group values into `n`-tuples.

``````julia> for i in partition(1:9, 3)
@show i
end
i = (1, 2, 3)
i = (4, 5, 6)
i = (7, 8, 9)``````

If the `step` parameter is set, each tuple is separated by `step` values.

``````julia> for i in partition(1:9, 3, 2)
@show i
end
i = (1, 2, 3)
i = (3, 4, 5)
i = (5, 6, 7)
i = (7, 8, 9)

julia> for i in partition(1:9, 3, 3)
@show i
end
i = (1, 2, 3)
i = (4, 5, 6)
i = (7, 8, 9)

julia> for i in partition(1:9, 2, 3)
@show i
end
i = (1, 2)
i = (4, 5)
i = (7, 8)``````
source

## ivec(xs)

Iterate over `xs` but do not preserve shape information.

``ivec(iter)``

Drops all shape from `iter` while iterating. Like a non-materializing version of `vec`.

``````julia> m = collect(reshape(1:6, 2, 3))
2×3 Array{Int64,2}:
1  3  5
2  4  6

julia> collect(ivec(m))
6-element Array{Int64,1}:
1
2
3
4
5
6``````
source

## peekiter(xs)

Peek at the head element of an iterator without updating the state.

``peekiter(xs)``

Lets you peek at the head element of an iterator without updating the state.

``````julia> it = peekiter(["face", "foo", "bar", "book", "baz", "zzz"])
IterTools.PeekIter{Array{String,1}}(["face", "foo", "bar", "book", "baz", "zzz"])

julia> @show peek(it);
peek(it) = Some("face")

julia> @show peek(it);
peek(it) = Some("face")

julia> x, s = iterate(it)
("face", ("foo", 3))

julia> @show x;
x = "face"

julia> @show peek(it, s);
peek(it, s) = Some("foo")``````
source

## repeatedly(f, [n])

Call a function `n` times, or infinitely if `n` is omitted.

``````repeatedly(f)
repeatedly(f, n)``````

Call function `f` `n` times, or infinitely if `n` is omitted.

``````julia> t() = (sleep(0.1); Dates.millisecond(now()))
t (generic function with 1 method)

julia> collect(repeatedly(t, 5))
5-element Array{Any,1}:
993
97
200
303
408``````
source

## takenth(xs, n)

Iterate through every n'th element of `xs`

``takenth(xs, n)``

Iterate through every `n`th element of `xs`.

``````julia> collect(takenth(5:15,3))
3-element Array{Int64,1}:
7
10
13``````
source

## subsets(xs, [k])

Iterate over every subset of an indexable collection `xs`, or iterate over every subset of size `k` from an indexable collection `xs`.

``````subsets(xs)
subsets(xs, k)
subsets(xs, Val{k}())``````

Iterate over every subset of the indexable collection `xs`. You can restrict the subsets to a specific size `k`.

Giving the subset size in the form `Val{k}()` allows the compiler to produce code optimized for the particular size requested. This leads to performance comparable to hand-written loops if `k` is small and known at compile time, but may or may not improve performance otherwise.

``````julia> for i in subsets([1, 2, 3])
@show i
end
i = Int64[]
i = 
i = 
i = [1, 2]
i = 
i = [1, 3]
i = [2, 3]
i = [1, 2, 3]

julia> for i in subsets(1:4, 2)
@show i
end
i = [1, 2]
i = [1, 3]
i = [1, 4]
i = [2, 3]
i = [2, 4]
i = [3, 4]

julia> for i in subsets(1:4, Val{2}())
@show i
end
i = (1, 2)
i = (1, 3)
i = (1, 4)
i = (2, 3)
i = (2, 4)
i = (3, 4)``````
source

## takestrict(xs, n)

Equivalent to `take`, but will throw an exception if fewer than `n` items are encountered in `xs`.

``takestrict(xs, n::Int)``

Like `take()`, an iterator that generates at most the first `n` elements of `xs`, but throws an exception if fewer than `n` items are encountered in `xs`.

``````julia> a = :1:2:11
1:2:11

julia> collect(takestrict(a, 3))
3-element Array{Int64,1}:
1
3
5``````
source

## takewhile(cond, xs)

Iterates through values from the iterable `xs` as long as a given predicate `cond` is true.

``takewhile(cond, xs)``

An iterator that yields values from the iterator `xs` as long as the predicate `cond` is true.

``````julia> collect(takewhile(x-> x^2 < 10, 1:100))
3-element Array{Int64,1}:
1
2
3``````
source

## flagfirst(xs)

Provide a flag to check if this is the first element.

``flagfirst(iter)``

An iterator that yields `(isfirst, x)` where `isfirst::Bool` is `true` for the first element, and `false` after that, while the `x`s are elements from `iter`.

``````julia> collect(flagfirst(1:3))
3-element Array{Tuple{Bool,Int64},1}:
(true, 1)
(false, 2)
(false, 3)``````
source

## IterTools.@ifsomething

Helper macro for returning from the enclosing block when there are no more elements.

``IterTools.@ifsomething expr``

If `expr` evaluates to `nothing`, equivalent to `return nothing`, otherwise the macro evaluates to the value of `expr`. Not exported, useful for implementing iterators.

``````julia> IterTools.@ifsomething iterate(1:2)
(1, 1)

julia> let elt, state = IterTools.@ifsomething iterate(1:2, 2); println("not reached"); end``````
source

## properties(x)

Iterate over struct or named tuple properties.

``properties(x)``

Iterate through the names and value of the properties of `x`.

``````julia> collect(properties(1 + 2im))
2-element Array{Any,1}:
(:re, 1)
(:im, 2)``````
source

## propertyvalues(x)

Iterate over struct or named tuple property values.

``propertyvalues``

## fieldvalues(x)

Like `(getfield(x, i) for i in 1:nfields(x))` but faster.

``fieldvalues(x)``

Iterate through the values of the fields of `x`.

``````julia> collect(fieldvalues(1 + 2im))
2-element Array{Any,1}:
1
2``````
source