module Iterator(T)
Overview
An Iterator
allows processing sequences lazily, as opposed to Enumerable
which processes sequences eagerly and produces an Array
in most of its methods.
As an example, let's compute the first three numbers in the range 1..10_000_000
that are even, multiplied by three. One way to do this is:
(1..10_000_000).select(&.even?).map { |x| x * 3 }.first(3) # => [6, 12, 18]
The above works, but creates many intermediate arrays: one for the select call, one for the map call and one for the take call. A more efficient way is to invoke Range#each
without a block, which gives us an Iterator
so we can process the operations lazily:
(1..10_000_000).each.select(&.even?).map { |x| x * 3 }.first(3) # => #< Iterator(T)::First...
Iterator
redefines many of Enumerable
's method in a lazy way, returning iterators instead of arrays.
At the end of the call chain we get back a new iterator: we need to consume it, either using #each
or Enumerable#to_a
:
(1..10_000_000).each.select(&.even?).map { |x| x * 3 }.first(3).to_a # => [6, 12, 18]
Because iterators only go forward, when using methods that consume it entirely or partially – to_a
, any?
, count
, none?
, one?
and size
– subsequent calls will give a different result as there will be less elements to consume.
iter = (0...100).each iter.size # => 100 iter.size # => 0
To implement an Iterator
you need to define a #next
method that must return the next element in the sequence or Iterator::Stop::INSTANCE
, which signals the end of the sequence (you can invoke #stop
inside an iterator as a shortcut).
For example, this is an iterator that returns a sequence of N
zeros:
class Zeros include Iterator(Int32) def initialize(@size : Int32) @produced = 0 end def next if @produced < @size @produced += 1 0 else stop end end end zeros = Zeros.new(5) zeros.to_a # => [0, 0, 0, 0, 0]
The standard library provides iterators for many classes, like Array
, Hash
, Range
, String
and IO
. Usually to get an iterator you invoke a method that would usually yield elements to a block, but without passing a block: Array#each
, Array#each_index
, Hash#each
, String#each_char
, IO#each_line
, etc.
Included Modules
Direct including types
Defined in:
iterator.crClass Method Summary
- .chain(iters : Iterator(Iter)) forall Iter
The same as
#chain
, but have better performance when the quantity of iterators to chain is large (usually greater than 4) or undetermined. - .chain(iters : Iterable(Iter)) forall Iter
the same as
.chain(Iterator(Iter))
- .of(element : T)
- .of(&block : -> T)
- .stop
Shortcut for
Iterator::Stop::INSTANCE
, to signal that there are no more elements in an iterator.
Instance Method Summary
- #accumulate(initial : U) forall U
Returns an iterator that returns initial and its prefix sums with the original iterator's elements.
- #accumulate
Returns an iterator that returns the prefix sums of the original iterator's elements.
- #accumulate(initial : U, &block : U, T -> U) forall U
Returns an iterator that accumulates initial with the original iterator's elements by the given block.
- #accumulate(&block : T, T -> T)
Returns an iterator that accumulates the original iterator's elements by the given block.
- #chain(other : Iterator(U)) forall U
Returns an iterator that returns elements from the original iterator until it is exhausted and then returns the elements of the second iterator.
- #chunk(reuse = false, &block : T -> U) forall T, U
Returns an Iterator that enumerates over the items, chunking them together based on the return value of the block.
- #chunk_while(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B
Returns an iterator for each chunked elements where elements are kept in a given chunk as long as the block's value over a pair of elements is truthy.
- #compact_map(&func : T -> _)
Returns an iterator that applies the given function to the element and then returns it unless it is
nil
. - #cons(n : Int, reuse = false)
Returns an iterator that returns consecutive chunks of the size n.
- #cons_pair : Iterator(Tuple(T, T))
Returns an iterator that returns consecutive pairs of adjacent items.
- #cycle(n : Int)
Returns an iterator that repeatedly returns the elements of the original iterator starting back at the beginning when the end was reached, but only n times.
- #cycle
Returns an iterator that repeatedly returns the elements of the original iterator forever starting back at the beginning when the end was reached.
- #each
- #each(& : T -> ) : Nil
Calls the given block once for each element, passing that element as a parameter.
- #each_slice(n, reuse = false)
Returns an iterator that then returns slices of n elements of the initial iterator.
- #first(n : Int)
Returns an iterator that only returns the first n elements of the initial iterator.
- #flat_map(&func : T -> _)
Returns a new iterator with the concatenated results of running the block once for every element in the collection.
- #flatten
Returns an iterator that flattens nested iterators and arrays into a single iterator whose type is the union of the simple types of all of the nested iterators and arrays (and their nested iterators and arrays, and so on).
- #in_groups_of(size : Int, filled_up_with = nil, reuse = false)
Returns an iterator that chunks the iterator's elements in arrays of size filling up the remaining elements if no element remains with
nil
or a given optional parameter. - #map(&func : T -> U) forall U
Returns an iterator that applies the given block to the next element and returns the result.
- #next
Returns the next element in this iterator, or
Iterator::Stop::INSTANCE
if there are no more elements. - #reject(&func : T -> U) forall U
Returns an iterator that only returns elements for which the passed in block returns a falsey value.
- #reject(type : U.class) forall U
Returns an iterator that only returns elements that are not of the given type.
- #reject(pattern)
Returns an iterator that only returns elements where
pattern === element
does not hold. - #select(&func : T -> U) forall U
Returns an iterator that only returns elements for which the passed in block returns a truthy value.
- #select(type : U.class) forall U
Returns an iterator that only returns elements of the given type.
- #select(pattern)
Returns an iterator that only returns elements where
pattern === element
. - #skip(n : Int)
Returns an iterator that skips the first n elements and only returns the elements after that.
- #skip_while(&func : T -> U) forall U
Returns an iterator that only starts to return elements once the given block has returned falsey value for one element.
- #slice(n : Int, reuse = false)
Alias of
#each_slice
. - #slice_after(reuse : Bool | Array(T) = false, &block : T -> B) forall B
Returns an iterator over chunks of elements, where each chunk ends right after the given block's value is truthy.
- #slice_after(pattern, reuse : Bool | Array(T) = false)
Returns an iterator over chunks of elements, where each chunk ends right after the given pattern is matched with
pattern === element
. - #slice_before(reuse : Bool | Array(T) = false, &block : T -> B) forall B
Returns an iterator over chunks of elements, where each chunk ends right before the given block's value is truthy.
- #slice_before(pattern, reuse : Bool | Array(T) = false)
Returns an iterator over chunks of elements, where each chunk ends right before the given pattern is matched with
pattern === element
. - #slice_when(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B
Returns an iterator for each chunked elements where the ends of chunks are defined by the block, when the block's value over a pair of elements is truthy.
- #step(n : Int)
Returns an iterator that only returns every nth element, starting with the first.
- #stop
Shortcut for
Iterator::Stop::INSTANCE
, to signal that there are no more elements in an iterator. - #take_while(&func : T -> U) forall U
Returns an iterator that returns elements while the given block returns a truthy value.
- #tap(&block : T -> )
Returns an iterator that calls the given block with the next element of the iterator when calling
#next
, still returning the original element. - #uniq
Returns an iterator that only returns unique values of the original iterator.
- #uniq(&func : T -> U) forall U
Returns an iterator that only returns unique values of the original iterator.
- #with_index(offset : Int = 0)
Returns an iterator that returns a
Tuple
of the element and its index. - #with_index(offset : Int = 0, &)
Yields each element in this iterator together with its index.
- #with_object(obj)
Returns an iterator that returns a
Tuple
of the element and a given object. - #with_object(obj, &)
Yields each element in this iterator together with obj.
- #zip(*others : Iterator) : Iterator
Returns an iterator that returns the elements of this iterator and others traversed in tandem as
Tuple
s.
Instance methods inherited from module Enumerable(T)
accumulate(initial : U) : Array(U) forall Uaccumulate : Array(T)
accumulate(initial : U, &block : U, T -> U) : Array(U) forall U
accumulate(&block : T, T -> T) : Array(T) accumulate, all?(& : T -> ) : Bool
all?(pattern) : Bool
all? : Bool all?, any?(& : T -> ) : Bool
any?(pattern) : Bool
any? : Bool any?, chunks(&block : T -> U) forall U chunks, compact_map(& : T -> _) compact_map, count(& : T -> ) : Int32
count(item) : Int32 count, cycle(n, & : T -> ) : Nil
cycle(& : T -> ) : Nil cycle, each(& : T -> ) each, each_cons(count : Int, reuse = false, &) each_cons, each_cons_pair(& : T, T -> ) : Nil each_cons_pair, each_slice(count : Int, reuse = false, &) each_slice, each_with_index(offset = 0, &) each_with_index, each_with_object(obj : U, & : T, U -> ) : U forall U each_with_object, empty? : Bool empty?, find(if_none = nil, & : T -> ) find, first(&)
first(count : Int) : Array(T)
first : T first, first? : T? first?, flat_map(& : T -> _) flat_map, group_by(& : T -> U) forall U group_by, in_groups_of(size : Int, filled_up_with : U = nil) forall U
in_groups_of(size : Int, filled_up_with : U = nil, reuse = false, &) forall U in_groups_of, includes?(obj) : Bool includes?, index(& : T -> ) : Int32?
index(obj) : Int32? index, index_by(& : T -> U) : Hash(U, T) forall U index_by, join(io : IO, separator = "") : Nil
join(separator, io : IO) : Nil
join(separator = "") : String
join(io : IO, separator = "", & : T, IO -> )
join(separator, io : IO, &)
join(separator = "", & : T -> ) join, map(& : T -> U) : Array(U) forall U map, map_with_index(offset = 0, & : T, Int32 -> U) : Array(U) forall U map_with_index, max : T max, max? : T? max?, max_by(& : T -> U) : T forall U max_by, max_by?(& : T -> U) : T? forall U max_by?, max_of(& : T -> U) : U forall U max_of, max_of?(& : T -> U) : U? forall U max_of?, min : T min, min? : T? min?, min_by(& : T -> U) : T forall U min_by, min_by?(& : T -> U) : T? forall U min_by?, min_of(& : T -> U) : U forall U min_of, min_of?(& : T -> U) : U? forall U min_of?, minmax : Tuple(T, T) minmax, minmax? : Tuple(T?, T?) minmax?, minmax_by(& : T -> U) : Tuple(T, T) forall U minmax_by, minmax_by?(& : T -> U) : Tuple(T, T) | Tuple(Nil, Nil) forall U minmax_by?, minmax_of(& : T -> U) : Tuple(U, U) forall U minmax_of, minmax_of?(& : T -> U) : Tuple(U, U) | Tuple(Nil, Nil) forall U minmax_of?, none?(& : T -> ) : Bool
none?(pattern) : Bool
none? : Bool none?, one?(& : T -> ) : Bool
one?(pattern) : Bool
one? : Bool one?, partition(& : T -> ) : Tuple(Array(T), Array(T)) partition, product(initial : Number)
product
product(initial : Number, & : T -> )
product(& : T -> _) product, reduce(memo, &)
reduce(&) reduce, reduce?(&) reduce?, reject(& : T -> )
reject(type : U.class) forall U
reject(pattern) : Array(T) reject, sample(n : Int, random = Random::DEFAULT) : Array(T)
sample(random = Random::DEFAULT) : T sample, select(& : T -> )
select(type : U.class) : Array(U) forall U
select(pattern) : Array(T) select, size : Int32 size, skip(count : Int) skip, skip_while(& : T -> ) : Array(T) skip_while, sum(initial)
sum
sum(initial, & : T -> )
sum(& : T -> ) sum, take_while(& : T -> ) : Array(T) take_while, tally : Hash(T, Int32) tally, tally_by(& : T -> U) : Hash(U, Int32) forall U tally_by, to_a to_a, to_h
to_h(& : T -> Tuple(K, V)) forall K, V to_h, to_set : Set(T) to_set, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator) zip, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator) zip?
Class methods inherited from module Enumerable(T)
element_type(x) element_type Class Method Detail
def self.chain(iters : Iterator(Iter)) forall IterSource
The same as #chain
, but have better performance when the quantity of iterators to chain is large (usually greater than 4) or undetermined.
array_of_iters = [[1], [2, 3], [4, 5, 6]].each.map &.each iter = Iterator(Int32).chain array_of_iters iter.next # => 1 iter.next # => 2 iter.next # => 3 iter.next # => 4
def self.chain(iters : Iterable(Iter)) forall IterSource
the same as .chain(Iterator(Iter))
def self.of(element : T)Source
def self.of(&block : -> T)Source
def self.stopSource
Shortcut for Iterator::Stop::INSTANCE
, to signal that there are no more elements in an iterator.
Instance Method Detail
def accumulate(initial : U) forall USource
Returns an iterator that returns initial and its prefix sums with the original iterator's elements.
Expects U
to respond to the #+
method.
iter = (3..6).each.accumulate(7) iter.next # => 7 iter.next # => 10 iter.next # => 14 iter.next # => 19 iter.next # => 25 iter.next # => Iterator::Stop::INSTANCE
def accumulateSource
Returns an iterator that returns the prefix sums of the original iterator's elements.
Expects T
to respond to the #+
method.
iter = (3..6).each.accumulate iter.next # => 3 iter.next # => 7 iter.next # => 12 iter.next # => 18 iter.next # => Iterator::Stop::INSTANCE
def accumulate(initial : U, &block : U, T -> U) forall USource
Returns an iterator that accumulates initial with the original iterator's elements by the given block.
Similar to #accumulate(&block : T, T -> T)
, except the initial value is provided by an argument and needs not have the same type as the elements of the original iterator. This initial value is returned first.
iter = [4, 3, 2].each.accumulate("X") { |x, y| x * y } iter.next # => "X" iter.next # => "XXXX" iter.next # => "XXXXXXXXXXXX" iter.next # => "XXXXXXXXXXXXXXXXXXXXXXXX" iter.next # => Iterator::Stop::INSTANCE
def accumulate(&block : T, T -> T)Source
Returns an iterator that accumulates the original iterator's elements by the given block.
For each element of the original iterator the block is passed an accumulator value and the element. The result becomes the new value for the accumulator and is then returned. The initial value for the accumulator is the first element of the original iterator.
iter = %w(the quick brown fox).each.accumulate { |x, y| "#{x}, #{y}" } iter.next # => "the" iter.next # => "the, quick" iter.next # => "the, quick, brown" iter.next # => "the, quick, brown, fox" iter.next # => Iterator::Stop::INSTANCE
def chain(other : Iterator(U)) forall USource
Returns an iterator that returns elements from the original iterator until it is exhausted and then returns the elements of the second iterator. Compared to .chain(Iterator(Iter))
, it has better performance when the quantity of iterators to chain is small (usually less than 4). This method also cannot chain iterators in a loop, for that see .chain(Iterator(Iter))
.
iter = (1..2).each.chain(('a'..'b').each) iter.next # => 1 iter.next # => 2 iter.next # => 'a' iter.next # => 'b' iter.next # => Iterator::Stop::INSTANCE
def chunk(reuse = false, &block : T -> U) forall T, USource
Returns an Iterator that enumerates over the items, chunking them together based on the return value of the block.
Consecutive elements which return the same block value are chunked together.
For example, consecutive even numbers and odd numbers can be chunked as follows.
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk(&.even?).each do |even, ary| p [even, ary] end # => [false, [3, 1]] # [true, [4]] # [false, [1, 5, 9]] # [true, [2, 6]] # [false, [5, 3, 5]]
The following key values have special meaning:
-
Enumerable::Chunk::Drop
specifies that the elements should be dropped -
Enumerable::Chunk::Alone
specifies that the element should be chunked by itself
By default, a new array is created and yielded for each chunk when invoking #next
.
- If reuse is given, the array can be reused
- If reuse is an
Array
, this array will be reused - If reuse is truthy, the method will create a new array and reuse it.
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
See also: Enumerable#chunks
.
def chunk_while(reuse : Bool | Array(T) = false, &block : T, T -> B) forall BSource
Returns an iterator for each chunked elements where elements are kept in a given chunk as long as the block's value over a pair of elements is truthy.
For example, one-by-one increasing subsequences can be chunked as follows:
ary = [1, 2, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21] iter = ary.chunk_while { |i, j| i + 1 == j } iter.next # => [1, 2] iter.next # => [4] iter.next # => [9, 10, 11, 12] iter.next # => [15, 16] iter.next # => [19, 20, 21] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
See also #slice_when
, which works similarly but the block's condition is inverted.
def compact_map(&func : T -> _)Source
Returns an iterator that applies the given function to the element and then returns it unless it is nil
. If the returned value would be nil
it instead returns the next non nil
value.
iter = [1, nil, 2, nil].each.compact_map { |e| e.try &.*(2) } iter.next # => 2 iter.next # => 4 iter.next # => Iterator::Stop::INSTANCE
def cons(n : Int, reuse = false)Source
Returns an iterator that returns consecutive chunks of the size n.
iter = (1..5).each.cons(3) iter.next # => [1, 2, 3] iter.next # => [2, 3, 4] iter.next # => [3, 4, 5] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and returned for each consecutive call of #next
.
- If reuse is given, the array can be reused
- If reuse is
true
, the method will create a new array and reuse it. - If reuse is an instance of
Array
,Deque
or a similar collection type (implementing#<<
,#shift
and#size
) it will be used. - If reuse is falsey, the array will not be reused.
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
Chunks of two items can be iterated using #cons_pair
, an optimized implementation for the special case of size == 2
which avoids heap allocations.
def cons_pair : Iterator(Tuple(T, T))Source
Returns an iterator that returns consecutive pairs of adjacent items.
iter = (1..5).each.cons_pair iter.next # => {1, 2} iter.next # => {2, 3} iter.next # => {3, 4} iter.next # => {4, 5} iter.next # => Iterator::Stop::INSTANCE
Chunks of more than two items can be iterated using #cons
. This method is just an optimized implementation for the special case of size == 2
to avoid heap allocations.
def cycle(n : Int)Source
Returns an iterator that repeatedly returns the elements of the original iterator starting back at the beginning when the end was reached, but only n times.
iter = ["a", "b", "c"].each.cycle(2) iter.next # => "a" iter.next # => "b" iter.next # => "c" iter.next # => "a" iter.next # => "b" iter.next # => "c" iter.next # => Iterator::Stop::INSTANCE
def cycleSource
Returns an iterator that repeatedly returns the elements of the original iterator forever starting back at the beginning when the end was reached.
iter = ["a", "b", "c"].each.cycle iter.next # => "a" iter.next # => "b" iter.next # => "c" iter.next # => "a" iter.next # => "b" iter.next # => "c" iter.next # => "a" # and so an and so on
def eachSource
def each(& : T -> ) : NilSource
Calls the given block once for each element, passing that element as a parameter.
iter = ["a", "b", "c"].each iter.each { |x| print x, " " } # Prints "a b c"
def each_slice(n, reuse = false)Source
Returns an iterator that then returns slices of n elements of the initial iterator.
iter = (1..9).each.each_slice(3) iter.next # => [1, 2, 3] iter.next # => [4, 5, 6] iter.next # => [7, 8, 9] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each consecutive when invoking #next
.
- If reuse is given, the array can be reused
- If reuse is an
Array
, this array will be reused - If reuse is truthy, the method will create a new array and reuse it.
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def first(n : Int)Source
Returns an iterator that only returns the first n elements of the initial iterator.
iter = ["a", "b", "c"].each.first 2 iter.next # => "a" iter.next # => "b" iter.next # => Iterator::Stop::INSTANCE
def flat_map(&func : T -> _)Source
Returns a new iterator with the concatenated results of running the block once for every element in the collection. Only Array
and Iterator
results are concatenated; every other value is returned once in the new iterator.
iter = [1, 2, 3].each.flat_map { |x| [x, x] } iter.next # => 1 iter.next # => 1 iter.next # => 2 iter = [1, 2, 3].each.flat_map { |x| [x, x].each } iter.to_a # => [1, 1, 2, 2, 3, 3]
def flattenSource
Returns an iterator that flattens nested iterators and arrays into a single iterator whose type is the union of the simple types of all of the nested iterators and arrays (and their nested iterators and arrays, and so on).
iter = [(1..2).each, ('a'..'b').each].each.flatten iter.next # => 1 iter.next # => 2 iter.next # => 'a' iter.next # => 'b' iter.next # => Iterator::Stop::INSTANCE
def in_groups_of(size : Int, filled_up_with = nil, reuse = false)Source
Returns an iterator that chunks the iterator's elements in arrays of size filling up the remaining elements if no element remains with nil
or a given optional parameter.
iter = (1..3).each.in_groups_of(2) iter.next # => [1, 2] iter.next # => [3, nil] iter.next # => Iterator::Stop::INSTANCE
iter = (1..3).each.in_groups_of(2, 'z') iter.next # => [1, 2] iter.next # => [3, 'z'] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each group.
- If reuse is given, the array can be reused
- If reuse is an
Array
, this array will be reused - If reuse is truthy, the method will create a new array and reuse it.
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def map(&func : T -> U) forall USource
Returns an iterator that applies the given block to the next element and returns the result.
iter = [1, 2, 3].each.map &.*(2) iter.next # => 2 iter.next # => 4 iter.next # => 6 iter.next # => Iterator::Stop::INSTANCE
abstract def nextSource
Returns the next element in this iterator, or Iterator::Stop::INSTANCE
if there are no more elements.
def reject(&func : T -> U) forall USource
Returns an iterator that only returns elements for which the passed in block returns a falsey value.
iter = [1, 2, 3].each.reject &.odd? iter.next # => 2 iter.next # => Iterator::Stop::INSTANCE
def reject(type : U.class) forall USource
Returns an iterator that only returns elements that are not of the given type.
iter = [1, false, 3, true].each.reject(Bool) iter.next # => 1 iter.next # => 3 iter.next # => Iterator::Stop::INSTANCE
def reject(pattern)Source
Returns an iterator that only returns elements where pattern === element
does not hold.
iter = [2, 3, 1, 5, 4, 6].each.reject(3..5) iter.next # => 2 iter.next # => 1 iter.next # => 6 iter.next # => Iterator::Stop::INSTANCE
def select(&func : T -> U) forall USource
Returns an iterator that only returns elements for which the passed in block returns a truthy value.
iter = [1, 2, 3].each.select &.odd? iter.next # => 1 iter.next # => 3 iter.next # => Iterator::Stop::INSTANCE
def select(type : U.class) forall USource
Returns an iterator that only returns elements of the given type.
iter = [1, false, 3, nil].each.select(Int32) iter.next # => 1 iter.next # => 3 iter.next # => Iterator::Stop::INSTANCE
def select(pattern)Source
Returns an iterator that only returns elements where pattern === element
.
iter = [1, 3, 2, 5, 4, 6].each.select(3..5) iter.next # => 3 iter.next # => 5 iter.next # => 4 iter.next # => Iterator::Stop::INSTANCE
def skip(n : Int)Source
Returns an iterator that skips the first n elements and only returns the elements after that.
iter = (1..3).each.skip(2) iter.next # -> 3 iter.next # -> Iterator::Stop::INSTANCE
def skip_while(&func : T -> U) forall USource
Returns an iterator that only starts to return elements once the given block has returned falsey value for one element.
iter = [1, 2, 3, 4, 0].each.skip_while { |i| i < 3 } iter.next # => 3 iter.next # => 4 iter.next # => 0 iter.next # => Iterator::Stop::INSTANCE
def slice(n : Int, reuse = false)Source
Alias of #each_slice
.
def slice_after(reuse : Bool | Array(T) = false, &block : T -> B) forall BSource
Returns an iterator over chunks of elements, where each chunk ends right after the given block's value is truthy.
For example, to get chunks that end at each uppercase letter:
ary = ['a', 'b', 'C', 'd', 'E', 'F', 'g', 'h'] # ^ ^ ^ iter = ary.slice_after(&.uppercase?) iter.next # => ['a', 'b', 'C'] iter.next # => ['d', 'E'] iter.next # => ['F'] iter.next # => ['g', 'h'] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def slice_after(pattern, reuse : Bool | Array(T) = false)Source
Returns an iterator over chunks of elements, where each chunk ends right after the given pattern is matched with pattern === element
.
For example, to get chunks that end at each ASCII uppercase letter:
ary = ['a', 'b', 'C', 'd', 'E', 'F', 'g', 'h'] # ^ ^ ^ iter = ary.slice_after('A'..'Z') iter.next # => ['a', 'b', 'C'] iter.next # => ['d', 'E'] iter.next # => ['F'] iter.next # => ['g', 'h'] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def slice_before(reuse : Bool | Array(T) = false, &block : T -> B) forall BSource
Returns an iterator over chunks of elements, where each chunk ends right before the given block's value is truthy.
For example, to get chunks that end just before each uppercase letter:
ary = ['a', 'b', 'C', 'd', 'E', 'F', 'g', 'h'] # ^ ^ ^ iter = ary.slice_before(&.uppercase?) iter.next # => ['a', 'b'] iter.next # => ['C', 'd'] iter.next # => ['E'] iter.next # => ['F', 'g', 'h'] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def slice_before(pattern, reuse : Bool | Array(T) = false)Source
Returns an iterator over chunks of elements, where each chunk ends right before the given pattern is matched with pattern === element
.
For example, to get chunks that end just before each ASCII uppercase letter:
ary = ['a', 'b', 'C', 'd', 'E', 'F', 'g', 'h'] # ^ ^ ^ iter = ary.slice_before('A'..'Z') iter.next # => ['a', 'b'] iter.next # => ['C', 'd'] iter.next # => ['E'] iter.next # => ['F', 'g', 'h'] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
def slice_when(reuse : Bool | Array(T) = false, &block : T, T -> B) forall BSource
Returns an iterator for each chunked elements where the ends of chunks are defined by the block, when the block's value over a pair of elements is truthy.
For example, one-by-one increasing subsequences can be chunked as follows:
ary = [1, 2, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21] iter = ary.slice_when { |i, j| i + 1 != j } iter.next # => [1, 2] iter.next # => [4] iter.next # => [9, 10, 11, 12] iter.next # => [15, 16] iter.next # => [19, 20, 21] iter.next # => Iterator::Stop::INSTANCE
By default, a new array is created and yielded for each slice when invoking #next
.
- If reuse is
false
, the method will create a new array for each chunk - If reuse is
true
, the method will create a new array and reuse it. - If reuse is an
Array
, that array will be reused
This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.
See also #chunk_while
, which works similarly but the block's condition is inverted.
def step(n : Int)Source
Returns an iterator that only returns every nth element, starting with the first.
iter = (1..6).each.step(2) iter.next # => 1 iter.next # => 3 iter.next # => 5 iter.next # => Iterator::Stop::INSTANCE
def stopSource
Shortcut for Iterator::Stop::INSTANCE
, to signal that there are no more elements in an iterator.
def take_while(&func : T -> U) forall USource
Returns an iterator that returns elements while the given block returns a truthy value.
iter = (1..5).each.take_while { |i| i < 3 } iter.next # => 1 iter.next # => 2 iter.next # => Iterator::Stop::INSTANCE
def tap(&block : T -> )Source
Returns an iterator that calls the given block with the next element of the iterator when calling #next
, still returning the original element.
a = 0 iter = (1..3).each.tap { |x| a += x } iter.next # => 1 a # => 1 iter.next # => 2 a # => 3 iter.next # => 3 a # => 6 iter.next # => Iterator::Stop::INSTANCE
def uniqSource
Returns an iterator that only returns unique values of the original iterator.
iter = [1, 2, 1].each.uniq iter.next # => 1 iter.next # => 2 iter.next # => Iterator::Stop::INSTANCE
def uniq(&func : T -> U) forall USource
Returns an iterator that only returns unique values of the original iterator. The provided block is applied to the elements to determine the value to be checked for uniqueness.
iter = [["a", "a"], ["b", "a"], ["a", "c"]].each.uniq &.first iter.next # => ["a", "a"] iter.next # => ["b", "a"] iter.next # => Iterator::Stop::INSTANCE
def with_index(offset : Int = 0)Source
Returns an iterator that returns a Tuple
of the element and its index.
iter = (1..3).each.with_index iter.next # => {1, 0} iter.next # => {2, 1} iter.next # => {3, 2} iter.next # => Iterator::Stop::INSTANCE
def with_index(offset : Int = 0, &)Source
Yields each element in this iterator together with its index.
def with_object(obj)Source
Returns an iterator that returns a Tuple
of the element and a given object.
iter = (1..3).each.with_object("a") iter.next # => {1, "a"} iter.next # => {2, "a"} iter.next # => {3, "a"} iter.next # => Iterator::Stop::INSTANCE
def with_object(obj, &)Source
Yields each element in this iterator together with obj. Returns that object.
def zip(*others : Iterator) : IteratorSource
Returns an iterator that returns the elements of this iterator and others traversed in tandem as Tuple
s.
Iteration stops when any of the iterators runs out of elements.
iter1 = [4, 5, 6].each iter2 = [7, 8, 9].each iter3 = ['a', 'b', 'c', 'd'].each iter = iter1.zip(iter2, iter3) iter.next # => {4, 7, 'a'} iter.next # => {5, 8, 'b'} iter.next # => {6, 9, 'c'} iter.next # => Iterator::Stop::INSTANCE
© 2012–2021 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/1.2.1/Iterator.html