View Source Iter (iterex v0.1.1)
Functions for working with iterators.
An iterator is a struct that wraps any value which implements the
Iter.Iterable
protocol. Lists, maps and ranges are all common data types
which can be used as iterators.
Explicit conversion
Whilst the Iter.Iterable
protocol is designed to work with many different
types, you must explicitly convert your iterables into an iterator using
Iter.from/1
. This allows for easy pattern matching of iterators as well as
for default implementations of Elixir's Enum
and Collectable
protocols.
Any value passed to Iter.from/1
must implement the Iter.IntoIterable
protocol.
Lazy by default
Like Elixir's Stream
, an Iter
is lazy by default. Any function which
returns an Iter.t
does so by simply composing iterables on top of each
other. No iteration is performed until it is needed, and then only the
minimum amount needed to return the result.
Summary
Functions
Returns true
if all elements in the iterator are truthy.
Returns true
if fun.(element)
is truthy for all elements in the iterator.
Returns true
if at least one element in the iterator is truthy.
Returns true
if fun.(element)
is truthy for at least one element in the
iterator.
Append a new element to the end of the iterable.
Return the element index
items from the beginning of the iterator.
Chunks the iterator by buffering elements for which fun
returns the same
value.
Shortcut to chunk_every(iterable, count, count)
.
Consumes the iterator in chunks, containing count
elements each, where each
new chunk steps step
elements into the iterator.
Chunks the iterator with fine grained control of when every chunk is emitted.
Creates an iterator that concatenates an iterator of iterators.
Creates an iterator that iterates the first argument, followed by the second argument.
Count the number of elements remaining in the iterator.
Count the number of elements for which fun
returns a truthy value.
Counts the elements in iterator stopping at limit
.
Counts the elements of iterator for which predicate
returns a truthy value, stopping at limit
.
Create an iterator that cycles it's elements eternally.
Remove consecutive duplicate elements from the iterator.
Remove consecutive elements for which fun
returns duplicate values from the iterator.
Returns a new iterator which drops the first how_many
elements.
Returns a new iterator with every nth
element in the iterator dropped,
starting with the first element.
Returns a new iterator which drops elements at the beginning of the iterator
until predicate
returns a truthy value.
Call fun
for every element in the iterator.
Returns an iterator that contains no elements.
Determines if the iterator is empty.
Remove elements for which predicate
returns a truthy value.
Searches for the first element in the iterator which matches predicate
.
Finds the index of the first value in the iterator that matches predicate
.
Similar to find/3
, but returns the value of the function invocation instead
of the element itself.
Maps fun
over the iterator flattening the result.
Flattens nested iterators.
Convert anything that implements Iter.IntoIterable
into an Iter
.
Intersperses separator
between each element of the iterator.
Is the passed value an iterator?
Emits a sequence of values, starting with start_value
. Successive values are
generated by calling next_fun
on the previous value.
Apply fun
to each element in the iterator and collect the result.
Creates a new iterator which applies mapper
on every nth
element of the
iterator, starting with the first element.
Returns the maximal element in the iterator according to Erlang's term sorting.
Returns the maximal element in the iterator as calculated by mapper
.
Checks if element
is a member of iterable
.
Returns the minimal element in the iterator according to Erlang's term sorting.
Returns the minimal element in the iterator as calculated by mapper
.
Returns the minimal and maximal element in the iterator according to Erlang's term ordering.
Advance the iterator and return the next value.
Peeks at the first element of the iterator, without consuming it.
Peeks at the first how_many
elements of the iterator, without consuming
them.
Prepend a new element to the beginning of the iterable.
Keep elements for which predicate
returns a truthy value.
Returns an iterator generated by calling generator_fun
repeatedly.
Create an iterator from a resource.
Creates an iterator starting at the same point, but stepping by step_size
each iteration.
Takes the next count
elements from the iterable and stops iteration.
Collects the first how_many
elements into a new iterator and returns it
along with the advanced initial iterator.
Creates an iterable which emits elements until predicate
returns false
.
Convert an iterator into a list.
Convert an iterator into an Elixir stream.
Creates a new iterator which returns only unique elements.
Creates a new iterator which replaces each element with a tuple containing the original element and the count of elements so far.
Zips corresponding elements from a finite collection of iterators into one iterator of tuples.
Zips to iterators together.
Zips corresponding elements from a finite collection of iterators into a new
iterator, transforming them with zip_fun
as it goes.
Zips corresponding elements from two iterators into a new one, transforming
them with zip_fun
as it goes.
Types
@type element() :: any()
@type predicate() :: (element() -> as_boolean(any()))
@type sorter() :: (element(), element() -> as_boolean(any()))
@type t() :: %Iter{iterable: Iter.Iterable.t()}
Functions
Returns true
if all elements in the iterator are truthy.
Examples
iex> [1, 2, false]
...> |> Iter.from()
...> |> Iter.all?()
false
iex> [1, 2, nil]
...> |> Iter.from()
...> |> Iter.all?()
false
iex> [1, 2, 3]
...> |> Iter.from()
...> |> Iter.all?()
true
Returns true
if fun.(element)
is truthy for all elements in the iterator.
Iterates over the iterator and invokes fun
on each element. If fun
ever
returns a falsy value (false
or nil
), iteration stops immediately and
false
is returned. Otherwise true
is returned.
Examples
iex> [2, 4, 6]
...> |> Iter.from()
...> |> Iter.all?(&(rem(&1, 2) == 0))
true
iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.all?(&(rem(&1, 2) == 0))
false
iex> []
...> |> Iter.from()
...> |> Iter.all?()
true
Returns true
if at least one element in the iterator is truthy.
When an element is a truthy value (neither false
nor nil
) iteration stops
immediately and true
is returned. In all other cases false
is returned.
Examples
iex> [false, false, false]
...> |> Iter.from()
...> |> Iter.any?()
false
iex> [false, true, false]
...> |> Iter.from()
...> |> Iter.any?()
true
iex> []
...> |> Iter.from()
...> |> Iter.any?()
false
Returns true
if fun.(element)
is truthy for at least one element in the
iterator.
Consumes the iterator and invokes fun
on each element. When an invocation
of fun
returns a truthy value (neither false
nor nil
) iteration stops
immediately and true
is returned. In all other cases false
is returned.
Examples
iex> [2, 4, 6]
...> |> Iter.from()
...> |> Iter.any?(&(rem(&1, 2) == 1))
false
iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.any?(&(rem(&1, 2) == 1))
true
iex> []
...> |> Iter.from()
...> |> Iter.any?(&(rem(&1, 2) == 1))
false
Append a new element to the end of the iterable.
Example
iex> 1..3
...> |> Iter.from()
...> |> Iter.append(4)
...> |> Iter.to_list()
[1, 2, 3, 4]
@spec at(t(), non_neg_integer()) :: {:ok, element(), t()} | :done
Return the element index
items from the beginning of the iterator.
Works by advancing the iterator the specified number of elements and then returning the element requested and an iterator of the remaining elements.
Return values
{:ok, element, new_iterator}
- the element requested and the iterator of the remaining elements.:done
- the iterator was exhausted before the element was found.
Examples
iex> 10..20
...> |> Iter.from()
...> |> Iter.at(5)
{:ok, 15, Iter.from(16..20)}
Chunks the iterator by buffering elements for which fun
returns the same
value.
Elements are only emitted when fun
returns a new value or iterable
is
exhausted.
Examples
iex> [1, 2, 2, 3, 4, 4, 6, 7, 7]
...> |> Iter.from()
...> |> Iter.chunk_by(&(rem(&1, 2) == 1))
...> |> Iter.to_list()
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]
@spec chunk_every(t(), pos_integer()) :: t()
Shortcut to chunk_every(iterable, count, count)
.
Consumes the iterator in chunks, containing count
elements each, where each
new chunk steps step
elements into the iterator.
step
is optional and, if not passed defaults to count
, i.e. chunks do not
overlap. Chunking will stop as soon as the iterable is exhausted or when we
emit an incomplete chunk.
If the last chunk does not have chunk
elements to fill the chunk, elements
are taken from leftover
to fill in the chunk, if leftover
does not have
enough elements to fill the chunk, then a partial chunk is returned with less
than count
elements.
If :discard
is given in leftover
the last chunk is discarded unless it has
exactly count
elements.
Examples
iex> [a, b, c] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(2)
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2]
iex> Iter.to_list(b)
[3, 4]
iex> Iter.to_list(c)
[5, 6]
iex> [a, b] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 2, :discard)
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[3, 4, 5]
iex> [a, b, c] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 2, [7] |> Iter.from())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[3, 4, 5]
iex> Iter.to_list(c)
[5, 6, 7]
iex> [a, b] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 3, [] |> Iter.from())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[4, 5, 6]
iex> [a, b] = [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 3, [0] |> Iter.from() |> Iter.cycle())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[4, 0, 0]
@spec chunk_every(t(), pos_integer(), pos_integer(), t() | :discard) :: Enumerable.t()
@spec chunk_while( t(), acc, (element(), acc -> {:cont, chunk, acc} | {:cont, acc} | {:halt, acc}), (acc -> {:cont, chunk, acc} | {:cont, acc}) ) :: t() when acc: any(), chunk: any()
Chunks the iterator with fine grained control of when every chunk is emitted.
chunk_fun
receives the current element and the accumulator and must return
{:cont, element, acc}
to emit the given chunk and continue with accumulator
or {:cont, acc}
to not emit any chunk and continue with the return
accumulator.
after_fun
is invoked when iteration is done and must also return {:cont, element, acc}
or {:cont, acc}
.
Examples
iex> chunk_fun = fn element, acc ->
...> if rem(element, 2) == 0 do
...> {:cont, Enum.reverse([element | acc]), []}
...> else
...> {:cont, [element | acc]}
...> end
...> end
iex> after_fun = fn
...> [] -> {:cont, []}
...> acc -> {:cont, Enum.reverse(acc), []}
...> end
iex> 1..10
...> |> Iter.from()
...> |> Iter.chunk_while([], chunk_fun, after_fun)
...> |> Iter.to_list()
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
Creates an iterator that concatenates an iterator of iterators.
Example
iex> [Iter.from(1..2), Iter.from(3..4)]
...> |> Iter.from()
...> |> Iter.concat()
...> |> Iter.to_list()
[1, 2, 3, 4]
Creates an iterator that iterates the first argument, followed by the second argument.
Example
iex> lhs = Iter.from(1..3)
...> rhs = Iter.from(4..6)
...> Iter.concat(lhs, rhs) |> Iter.to_list()
[1, 2, 3, 4, 5, 6]
@spec count(t()) :: non_neg_integer()
Count the number of elements remaining in the iterator.
Some iterators can be counted without consuming the iterator, but most cannot and you should consider the iterator passed to this function as having been exhausted.
Example
iex> 1..10
...> |> Iter.from()
...> |> Iter.count()
10
@spec count(t(), (element() -> as_boolean(any()))) :: non_neg_integer()
Count the number of elements for which fun
returns a truthy value.
Example
iex> 1..5
...> |> Iter.from()
...> |> Iter.count(&(rem(&1, 2) == 0))
2
@spec count_until(t(), pos_integer()) :: {:ok, non_neg_integer(), t()}
Counts the elements in iterator stopping at limit
.
Examples
iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 5, Iter.from(6..20)}
iex> 1..3
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 3, Iter.empty()}
iex> []
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 0, Iter.empty()}
@spec count_until(t(), predicate(), pos_integer()) :: {:ok, non_neg_integer(), t()}
Counts the elements of iterator for which predicate
returns a truthy value, stopping at limit
.
Examples
iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(&(rem(&1, 2) == 0), 7)
{:ok, 7, Iter.from(15..20)}
iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(&(rem(&1, 2) == 0), 11)
{:ok, 10, Iter.empty()}
Create an iterator that cycles it's elements eternally.
iex> [:a, :b, :c]
...> |> Iter.from()
...> |> Iter.cycle()
...> |> Iter.take(5)
...> |> Iter.to_list()
[:a, :b, :c, :a, :b]
Remove consecutive duplicate elements from the iterator.
Example
iex> [1, 1, 2, 3, 3, 4, 5, 4]
...> |> Iter.from()
...> |> Iter.dedup()
...> |> Iter.to_list()
[1, 2, 3, 4, 5, 4]
Remove consecutive elements for which fun
returns duplicate values from the iterator.
Example
iex> [{1, :a}, {2, :b}, {2, :c}, {1, :a}] ...> |> Iter.from() ...> |> Iter.dedup_by(&elem(&1, 0)) ...> |> Iter.to_list() [{1, :a}, {2, :b}, {1, :a}]
@spec drop(t(), non_neg_integer()) :: t()
Returns a new iterator which drops the first how_many
elements.
Examples
iex> 1..3
...> |> Iter.from()
...> |> Iter.drop(2)
...> |> Iter.to_list()
[3]
@spec drop_every(t(), non_neg_integer()) :: t()
Returns a new iterator with every nth
element in the iterator dropped,
starting with the first element.
Examples
iex> 1..10
...> |> Iter.from()
...> |> Iter.drop_every(2)
...> |> Iter.to_list()
[2, 4, 6, 8, 10]
iex> 1..10
...> |> Iter.from()
...> |> Iter.drop_every(0)
...> |> Iter.to_list()
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
iex> [1, 2, 3]
...> |> Iter.from()
...> |> Iter.drop_every(1)
...> |> Iter.to_list()
[]
Returns a new iterator which drops elements at the beginning of the iterator
until predicate
returns a truthy value.
Example
iex> [1, 2, 3, 2, 1]
...> |> Iter.from()
...> |> Iter.drop_while(&(&1 < 3))
...> |> Iter.to_list()
[3, 2, 1]
Call fun
for every element in the iterator.
The return value is not used.
Example
["marty", "doc"]
|> Iter.from()
|> Iter.each(&IO.puts/1)
"marty"
"doc"
#=> :done
@spec empty() :: t()
Returns an iterator that contains no elements.
Example
iex> Iter.empty()
...> |> Iter.to_list()
[]
Determines if the iterator is empty.
Examples
iex> Iter.empty()
...> |> Iter.empty?()
true
iex> 1..20
...> |> Iter.from()
...> |> Iter.empty?
false
Remove elements for which predicate
returns a truthy value.
Example
iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.filter(&(rem(&1, 2) == 0))
...> |> Iter.to_list()
[2, 4]
Searches for the first element in the iterator which matches predicate
.
Example
iex> [1, 2, 3, 4, 5]
...> |> Iter.from()
...> |> Iter.find(&(&1 > 3))
{:ok, 4, Iter.from([5])}
iex> [1, 2, 3]
...> |> Iter.from()
...> |> Iter.find(&(&1 > 4))
:done
@spec find_index(t(), predicate()) :: {:ok, non_neg_integer(), t()} | :done
Finds the index of the first value in the iterator that matches predicate
.
Example
iex> [1, 2, 3, 4, 5]
...> |> Iter.from()
...> |> Iter.find_index(&(&1 > 3))
{:ok, 3, Iter.from([5])}
Similar to find/3
, but returns the value of the function invocation instead
of the element itself.
Example
iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.find_value(fn x ->
...> if x > 2, do: x * x
...> end)
{:ok, 9, Iter.from([4])}
iex> [2, 4, 6]
...> |> Iter.from()
...> |> Iter.find_value(&(rem(&1, 2) == 1))
:done
iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.find_value(&(rem(&1, 2) == 1))
{:ok, true, Iter.from([4])}
Maps fun
over the iterator flattening the result.
Example
iex> [:a, :b, :c]
...> |> Iter.from()
...> |> Iter.flat_map(&Iter.from([&1, &1]))
...> |> Iter.to_list()
[:a, :a, :b, :b, :c, :c]
Flattens nested iterators.
Example
iex> [[:a, :a], [:b, :b], [:c, :c]]
...> |> Iter.from()
...> |> Iter.flatten()
...> |> Iter.to_list()
[:a, :a, :b, :b, :c, :c]
@spec from(Iter.IntoIterable.t()) :: t()
Convert anything that implements Iter.IntoIterable
into an Iter
.
Intersperses separator
between each element of the iterator.
Examples
iex> 1..3
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[1, 0, 2, 0, 3]
iex> [1]
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[1]
iex> []
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[]
@spec is_iter(any()) :: Macro.output()
Is the passed value an iterator?
Emits a sequence of values, starting with start_value
. Successive values are
generated by calling next_fun
on the previous value.
iex> Iter.iterate(0, &(&1 + 1))
...> |> Iter.take(5)
...> |> Iter.to_list()
[0, 1, 2, 3, 4]
Apply fun
to each element in the iterator and collect the result.
Example
iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.map(&(&1 * 2))
...> |> Iter.to_list()
[2, 4, 6, 8]
@spec map_every(t(), non_neg_integer(), (element() -> new_element)) :: t() when new_element: any()
Creates a new iterator which applies mapper
on every nth
element of the
iterator, starting with the first element.
The first element is always mapped unless nth
is 0
.
Examples
iex> 1..10
...> |> Iter.from()
...> |> Iter.map_every(2, fn x -> x + 1000 end)
...> |> Iter.to_list()
[1001, 2, 1003, 4, 1005, 6, 1007, 8, 1009, 10]
iex> 1..10
...> |> Iter.from()
...> |> Iter.map_every(3, fn x -> x + 1000 end)
...> |> Iter.to_list()
[1001, 2, 3, 1004, 5, 6, 1007, 8, 9, 1010]
iex> 1..5
...> |> Iter.from()
...> |> Iter.map_every(0, fn x -> x + 1000 end)
...> |> Iter.to_list()
[1, 2, 3, 4, 5]
iex> 1..3
...> |> Iter.from()
...> |> Iter.map_every(1, fn x -> x + 1000 end)
...> |> Iter.to_list()
[1001, 1002, 1003]
Returns the maximal element in the iterator according to Erlang's term sorting.
Example
iex> [1, 4, 3, 2]
...> |> Iter.from()
...> |> Iter.max()
{:ok, 4}
iex> Iter.empty()
...> |> Iter.max()
:done
Returns the maximal element in the iterator as calculated by mapper
.
Example
iex> ["a", "aa", "aaa"]
...> |> Iter.from()
...> |> Iter.max_by(&String.length/1)
{:ok, "aaa"}
iex> Iter.empty()
...> |> Iter.max_by(&String.length/1)
:done
Checks if element
is a member of iterable
.
Examples
iex> 1..5
...> |> Iter.from()
...> |> Iter.member?(3)
true
iex> 1..5
...> |> Iter.from()
...> |> Iter.member?(6)
false
Returns the minimal element in the iterator according to Erlang's term sorting.
Example
iex> [1, 4, 3, 2]
...> |> Iter.from()
...> |> Iter.min()
{:ok, 1}
Returns the minimal element in the iterator as calculated by mapper
.
Example
iex> ["a", "aa", "aaa"]
...> |> Iter.from()
...> |> Iter.min_by(&String.length/1)
{:ok, "a"}
iex> Iter.empty()
...> |> Iter.min_by(&String.length/1)
:done
Returns the minimal and maximal element in the iterator according to Erlang's term ordering.
Example
iex> [2, 3, 1]
...> |> Iter.from()
...> |> Iter.min_max()
{:ok, 1, 3}
iex> Iter.empty()
...> |> Iter.min_max()
:done
Advance the iterator and return the next value.
Return values
{:ok, element, new_iterator}
- returns the next element and an updated iterator.:done
- the iterator is exhausted.
Peeks at the first element of the iterator, without consuming it.
Warning
Many iterators cannot be peeked, so this function simulates peeking by consuming an element from the iterator and returning a new iterator which pushes that element back onto the front.
Example
iex> {:ok, 1, iter} = 1..3
...> |> Iter.from()
...> |> Iter.peek()
...> Iter.to_list(iter)
[1, 2, 3]
@spec peek(t(), how_many :: pos_integer()) :: {:ok, [element()], non_neg_integer(), t()} | :done
Peeks at the first how_many
elements of the iterator, without consuming
them.
Warning
Many iterables cannot be peeked, so this function simulates peeking by consuming elements from the iterator and returning a new iterator which pushes those elements back on to the front.
Because it's possible to try and peek past the end of an iterator you shouldn't expect the number of elements returned to always be the same as how many you asked for. For this reason the return value includes the number of elements that were able to be peeked.
Example
iex> {:ok, peeks, 3, iter} = 1..5
...> |> Iter.from()
...> |> Iter.peek(3)
iex> Iter.to_list(peeks)
[1, 2, 3]
iex> Iter.to_list(iter)
[1, 2, 3, 4, 5]
iex> {:ok, peeks, 3, iter} = 1..3
...> |> Iter.from()
...> |> Iter.peek(5)
iex> Iter.to_list(peeks)
[1, 2, 3]
iex> Iter.to_list(iter)
[1, 2, 3]
Prepend a new element to the beginning of the iterable.
Example
iex> 1..3
...> |> Iter.from()
...> |> Iter.prepend(4)
...> |> Iter.to_list()
[4, 1, 2, 3]
Keep elements for which predicate
returns a truthy value.
Example
iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.reject(&(rem(&1, 2) == 0))
...> |> Iter.to_list()
[1, 3]
Returns an iterator generated by calling generator_fun
repeatedly.
Examples
# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.repeatedly(&:rand.uniform/0) |> Iter.take(3) |> Iter.to_list()
[0.5455598952593053, 0.6039309974353404, 0.6684893034823949]
@spec resource( start_fun :: (-> acc), next_fun :: (acc -> {[element()], acc} | {:halt, acc}), after_fun :: (acc -> any()) ) :: t() when acc: any()
Create an iterator from a resource.
iex> Iter.resource(
...> fn ->
...> {:ok, pid} = StringIO.open("Marty")
...> pid
...> end,
...> fn pid ->
...> case IO.read(pid, 1) do
...> :eof -> {:halt, pid}
...> char -> {[char], pid}
...> end
...> end,
...> fn pid ->
...> StringIO.close(pid)
...> end
...> )
...> |> Iter.to_list()
["M", "a", "r", "t", "y"]
@spec step_by(t(), pos_integer()) :: t()
Creates an iterator starting at the same point, but stepping by step_size
each iteration.
The first element of the iterator will always be returned, regardless of the step given.
Examples
iex> 1..9
...> |> Iter.from()
...> |> Iter.step_by(3)
...> |> Iter.to_list()
[1, 4, 7]
Takes the next count
elements from the iterable and stops iteration.
If a negative count is given, the last count values will be taken. For such,
the collection is fully enumerated keeping up to count
elements in memory.
Once the end of the collection is reached, the last count
elements will be
iterated. Therefore, using a negative count on an infinite collection will
never return.
The rest of the underlying iterable is discarded.
Examples
iex> Iter.empty()
...> |> Iter.take(3)
...> |> Iter.to_list()
[]
iex> Iter.empty()
...> |> Iter.take(-3)
...> |> Iter.to_list()
[]
iex> 1..5
...> |> Iter.from()
...> |> Iter.take(3)
...> |> Iter.to_list()
[1, 2, 3]
iex> 1..5
...> |> Iter.from()
...> |> Iter.take(-3)
...> |> Iter.to_list()
[3, 4, 5]
@spec take_chunk(t(), pos_integer()) :: {:ok, t(), t()} | {:done, t()}
Collects the first how_many
elements into a new iterator and returns it
along with the advanced initial iterator.
This is very much like take/2
except that it returns the remaining iterator
so that it can be called repeatedly.
Example
iex> iter = Iter.from(1..9)
...> {:ok, chunk_a, iter} = Iter.take_chunk(iter, 3)
...> {:ok, chunk_b, remainder} = Iter.take_chunk(iter, 3)
...> Iter.to_list(chunk_a)
[1, 2, 3]
iex> Iter.to_list(chunk_b)
[4, 5, 6]
iex> Iter.to_list(remainder)
[7, 8, 9]
Creates an iterable which emits elements until predicate
returns false
.
The rest of the underlying iterable is discarded.
Example
iex> 1..3
...> |> Iter.from()
...> |> Iter.take_while(&(&1 < 3))
...> |> Iter.to_list()
[1, 2]
Convert an iterator into a list.
@spec to_stream(t()) :: Enumerable.t()
Convert an iterator into an Elixir stream.
Example
iex> [:a, :b, :c]
...> |> Iter.from()
...> |> Iter.cycle()
...> |> Iter.to_stream()
...> |> Enum.take(5)
[:a, :b, :c, :a, :b]
Creates a new iterator which returns only unique elements.
Warning
Except for specific data structures (eg
MapSet
andRange
) most iterators will need to store a set of "seen values" in order to provide this function. In such cases memory usage will grow in direct relation to the number of unique elements in the iterator.
Example
iex> 1..5
...> |> Iter.from()
...> |> Iter.uniq()
Iter.from(1..5)
iex> [1, 2, 3, 2, 1]
...> |> Iter.from()
...> |> Iter.uniq()
...> |> Iter.to_list()
[1, 2, 3]
Creates a new iterator which replaces each element with a tuple containing the original element and the count of elements so far.
Example
iex> 1..3
...> |> Iter.from()
...> |> Iter.with_index()
...> |> Iter.to_list()
[{1, 0}, {2, 1}, {3, 2}]
Zips corresponding elements from a finite collection of iterators into one iterator of tuples.
The zipping finishes as soon as any iterable in the collection is exhausted.
Example
iex> first = Iter.from(1..3)
...> second = Iter.from([:a, :b, :c])
...> third = Iter.from(["a", "b", "c"])
...> [first, second, third]
...> |> Iter.from()
...> |> Iter.zip()
...> |> Iter.to_list()
[{1, :a, "a"}, {2, :b, "b"}, {3, :c, "c"}]
Zips to iterators together.
The zipping finishes as soon as either iterator is exhausted.
Example
iex> first = Iter.from(1..3)
...> second = Iter.from([:a, :b, :c])
...> Iter.zip(first, second)
...> |> Iter.to_list()
[{1, :a}, {2, :b}, {3, :c}]
Zips corresponding elements from a finite collection of iterators into a new
iterator, transforming them with zip_fun
as it goes.
The first element from each of the iterators will be put into a list which is
then passed to the one-arity zip_fun
function. Then, the second elements
from each of the iterators are put into a list, and so on until any of the
iterators are exhausted.
Example
iex> first = Iter.from(1..3)
...> second = Iter.from(4..6)
...> third = Iter.from(7..9)
...> [first, second, third]
...> |> Iter.from()
...> |> Iter.zip_with(fn [a, b, c] -> a + b + c end)
...> |> Iter.to_list()
[12, 15, 18]
Zips corresponding elements from two iterators into a new one, transforming
them with zip_fun
as it goes.
The zip_fun
will be called with the first elements from the iterators, then
the second elements and so on.
Example
iex> first = Iter.from(1..3)
...> second = Iter.from(4..6)
...> Iter.zip_with(first, second, &(&1 + &2))
...> |> Iter.to_list()
[5, 7, 9]