Title: | Iterators for efficient looping |
---|---|
Description: | A port of Python's excellent itertools module to R for efficient looping. |
Authors: | John A. Ramey <[email protected]>, Kayla Schaefer <[email protected]> |
Maintainer: | John A. Ramey <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.1.3 |
Built: | 2024-11-17 03:24:01 UTC |
Source: | https://github.com/ramhiser/itertools2 |
Advances the iterator n-steps ahead without returning anything.
consume(iterator, n = 0)
consume(iterator, n = 0)
iterator |
an iterator object |
n |
The number of elements to consume. |
If n
is 0, the iterator is consumed entirely. Similarly, if n
is larger than the length of the iterator, the iterator is consumed entirely.
Nothing, i.e., invisible(NULL)
it <- iterators::iter(1:10) # Skips the first 5 elements consume(it, n=5) # Returns 6 iterators::nextElem(it) it2 <- iterators::iter(letters) # Skips the first 4 elements consume(it2, 4) # Returns 'e' iterators::nextElem(it2)
it <- iterators::iter(1:10) # Skips the first 5 elements consume(it, n=5) # Returns 6 iterators::nextElem(it) it2 <- iterators::iter(letters) # Skips the first 4 elements consume(it2, 4) # Returns 'e' iterators::nextElem(it2)
Returns the dot product of two numeric iterables of equal length
dotproduct(vec1, vec2)
dotproduct(vec1, vec2)
vec1 |
the first |
vec2 |
the second iterable object |
the dot product of the iterators
it <- iterators::iter(1:3) it2 <- iterators::iter(4:6) dotproduct(it, it2) # 32 it <- iterators::iter(1:4) it2 <- iterators::iter(7:10) dotproduct(1:4, 7:10) # 90
it <- iterators::iter(1:3) it2 <- iterators::iter(4:6) dotproduct(it, it2) # 32 it <- iterators::iter(1:4) it2 <- iterators::iter(7:10) dotproduct(1:4, 7:10) # 90
Generates an iterator that returns elements from the first argument until it is exhausted. Then generates an iterator from the next argument and returns elements from it. This process continues until all arguments are exhausted Chaining is useful for treating consecutive sequences as a single sequence.
ichain(...)
ichain(...)
... |
multiple arguments to iterate through in sequence |
iterator that iterates through each argument in sequence
it <- ichain(1:3, 4:5, 6) as.list(it) it2 <- ichain(1:3, levels(iris$Species)) as.list(it2)
it <- ichain(1:3, 4:5, 6) as.list(it) it2 <- ichain(1:3, levels(iris$Species)) as.list(it2)
Constructs an iterator that returns elements of an iterable object
in
fixed-length chunks. If the length of the iterator is not divisible by
chunk_size
, the remainder of the last block is filled with the value
specified in fill
.
ichunk(object, chunk_size = 1, fill = NA)
ichunk(object, chunk_size = 1, fill = NA)
object |
an iterable object |
chunk_size |
the number of elements returned per chunk |
fill |
the value with which to fill the last chunk if the length of the
iterator is not divisble by |
This function corresponds to Python's grouper
function. We chose the
name ichunk
because it more explicitly defines the function's purpose.
each call to nextElem
results in a list of length
chunk_size
it <- ichunk(iterators::iter(1:5), chunk_size=2) # List: list(1, 2, 3) iterators::nextElem(it) # List: list(4, 5, NA) iterators::nextElem(it) it2 <- ichunk(levels(iris$Species), chunk_size=4, "weeee") # Returns: list("setosa", "versicolor", "virginica", "weeee") iterators::nextElem(it2)
it <- ichunk(iterators::iter(1:5), chunk_size=2) # List: list(1, 2, 3) iterators::nextElem(it) # List: list(4, 5, NA) iterators::nextElem(it) it2 <- ichunk(levels(iris$Species), chunk_size=4, "weeee") # Returns: list("setosa", "versicolor", "virginica", "weeee") iterators::nextElem(it2)
Constructs an iterator generates all combinations of a vector taken m
at a time. This function is similar to combn
.
icombinations(object, m, replacement = FALSE)
icombinations(object, m, replacement = FALSE)
object |
vector |
m |
the length of each combination |
replacement |
Generate combinations with replacement? Default: no. |
By default, the combinations are **without replacement** so that elements are
not repeated. To generate combinations **with replacement**, set
replacement=TRUE
.
The function implementation is loosely based on the combinations
function from Python's itertools. Combinations with replacement are based on
combinations_with_replacement
from the same Python library.
iterator that generates all combinations of object
# Combinations without replacement it <- icombinations(1:4, m=2) iterators::nextElem(it) # c(1, 2) iterators::nextElem(it) # c(1, 3) iterators::nextElem(it) # c(1, 4) iterators::nextElem(it) # c(2, 3) iterators::nextElem(it) # c(2, 4) iterators::nextElem(it) # c(3, 4) # Combinations without replacement it <- icombinations(1:4, m=2, replacement=TRUE) iterators::nextElem(it) # c(1, 1) iterators::nextElem(it) # c(1, 2) iterators::nextElem(it) # c(1, 3) iterators::nextElem(it) # c(1, 4) iterators::nextElem(it) # c(2, 2) iterators::nextElem(it) # c(2, 3) iterators::nextElem(it) # c(2, 4) iterators::nextElem(it) # c(3, 3) iterators::nextElem(it) # c(3, 4) iterators::nextElem(it) # c(4, 4) it3 <- icombinations(1:5, m=2) as.list(it3) utils::combn(x=1:5, m=2, simplify=FALSE)
# Combinations without replacement it <- icombinations(1:4, m=2) iterators::nextElem(it) # c(1, 2) iterators::nextElem(it) # c(1, 3) iterators::nextElem(it) # c(1, 4) iterators::nextElem(it) # c(2, 3) iterators::nextElem(it) # c(2, 4) iterators::nextElem(it) # c(3, 4) # Combinations without replacement it <- icombinations(1:4, m=2, replacement=TRUE) iterators::nextElem(it) # c(1, 1) iterators::nextElem(it) # c(1, 2) iterators::nextElem(it) # c(1, 3) iterators::nextElem(it) # c(1, 4) iterators::nextElem(it) # c(2, 2) iterators::nextElem(it) # c(2, 3) iterators::nextElem(it) # c(2, 4) iterators::nextElem(it) # c(3, 3) iterators::nextElem(it) # c(3, 4) iterators::nextElem(it) # c(4, 4) it3 <- icombinations(1:5, m=2) as.list(it3) utils::combn(x=1:5, m=2, simplify=FALSE)
Constructs an iterator that filters elements from iterable returning only
those for which the corresponding element from selectors
is
TRUE
.
icompress(object, selectors)
icompress(object, selectors)
object |
an iterable object |
selectors |
an iterable that determines whether the corresponding
element in |
The iterator stops when either object
or selectors
has been
exhausted.
iterator object
# Filters out odd numbers and retains only even numbers n <- 10 selectors <- rep(c(FALSE, TRUE), n) it <- icompress(seq_len(n), selectors) as.list(it) # Similar idea here but anonymous function is used to filter out even # numbers n <- 10 it2 <- icompress(seq_len(10), rep(c(TRUE, FALSE), n)) as.list(it2) it3 <- icompress(letters, letters %in% c('a', 'e', 'i', 'o', 'u')) as.list(it3)
# Filters out odd numbers and retains only even numbers n <- 10 selectors <- rep(c(FALSE, TRUE), n) it <- icompress(seq_len(n), selectors) as.list(it) # Similar idea here but anonymous function is used to filter out even # numbers n <- 10 it2 <- icompress(seq_len(10), rep(c(TRUE, FALSE), n)) as.list(it2) it3 <- icompress(letters, letters %in% c('a', 'e', 'i', 'o', 'u')) as.list(it3)
Constructs an iterator that generates a sequence of evenly spaced values
starting with icount
. The step size is given by step
. By
default, the sequence is neverending unless the optional stop
is
provided.
icount(start = 0, step = 1, stop = NULL)
icount(start = 0, step = 1, stop = NULL)
start |
sequence's initial value |
step |
sequence's step size |
stop |
optional stopping point to sequence |
NOTE: Use a negative step
size to generate decreasing sequences.
Often used as an argument to imap
to
generate consecutive data points.
sequence's iterator
it <- icount() iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) it2 <- icount(start=5.5, step=1.5) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) it3 <- icount(start=1, stop=3) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3)
it <- icount() iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) it2 <- icount(start=5.5, step=1.5) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) it3 <- icount(start=1, stop=3) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3)
Constructs an iterator that returns an iterable object in sequence over and over again.
icycle(object, times = NULL)
icycle(object, times = NULL)
object |
object to cycle indefinitely. |
times |
the number of times |
Runs indefinitely unless the times
argument is specified.
iterator that returns object
in sequence
it <- icycle(1:3) iterators::nextElem(it) # 1 iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 1 iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 1 it2 <- icycle(1:3, times=2) as.list(it2) # Can return the results from a function. it3 <- icycle(function() rnorm(1)) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it)
it <- icycle(1:3) iterators::nextElem(it) # 1 iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 1 iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 1 it2 <- icycle(1:3, times=2) as.list(it2) # Can return the results from a function. it3 <- icycle(function() rnorm(1)) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it)
Constructs an iterator that drops elements from the iterable object
as
long as the predicate
function is true; afterwards, every element of
iterable
object is returned.
idropwhile(predicate, object)
idropwhile(predicate, object)
predicate |
a function that determines whether an element is |
object |
an iterable object |
Because the iterator does not return any elements until the predicate
first becomes false, there may have a lengthy start-up time before elements
are returned.
iterator object
# Filters out numbers exceeding 3 not_too_large <- function(x) { x <= 3 } it <- idropwhile(not_too_large, 1:8) as.list(it) # Same approach but uses an anonymous function it2 <- idropwhile(function(x) x <= 10, seq(2, 20, by=2)) as.list(it2)
# Filters out numbers exceeding 3 not_too_large <- function(x) { x <= 3 } it <- idropwhile(not_too_large, 1:8) as.list(it) # Same approach but uses an anonymous function it2 <- idropwhile(function(x) x <= 10, seq(2, 20, by=2)) as.list(it2)
Constructs an iterator that returns the elements of an object along with each
element's indices. Enumeration is useful when looping through an
object
and a counter is required.
ienumerate(object) ienum(object)
ienumerate(object) ienum(object)
object |
object to return indefinitely. |
This function is intended to follow the convention used in Python's
enumerate
function where the primary difference is that a list is
returned instead of Python's tuple
construct.
Each call to nextElem
returns a list with two
elements:
a counter
the current value of object
ienum
is an alias to ienumerate
to save a few keystrokes.
iterator that returns the values of object
along with the
index of the object.
set.seed(42) it <- ienumerate(rnorm(5)) as.list(it) # Iterates through the columns of the iris data.frame it2 <- ienum(iris) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2)
set.seed(42) it <- ienumerate(rnorm(5)) as.list(it) # Iterates through the columns of the iris data.frame it2 <- ienum(iris) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2)
Constructs an iterator that filters elements from iterable returning only
those for which the predicate is TRUE
.
Constructs an iterator that filters elements from iterable returning only
those for which the predicate is FALSE
.
ifilter(predicate, iterable) ifilterfalse(predicate, iterable)
ifilter(predicate, iterable) ifilterfalse(predicate, iterable)
predicate |
a function that determines whether an element is |
iterable |
an iterable object |
iterator object
# Filters out odd numbers and retains only even numbers is_even <- function(x) { x %% 2 == 0 } it <- ifilter(is_even, 1:10) as.list(it) # Similar idea here but anonymous function is used to filter out even # numbers it2 <- ifilter(function(x) x %% 2 == 1, 1:10) iterators::nextElem(it2) # 1 iterators::nextElem(it2) # 3 iterators::nextElem(it2) # 5 iterators::nextElem(it2) # 7 iterators::nextElem(it2) # 9 is_vowel <- function(x) { x %in% c('a', 'e', 'i', 'o', 'u') } it3 <- ifilter(is_vowel, letters) as.list(it3) # Filters out even numbers and retains only odd numbers is_even <- function(x) { x %% 2 == 0 } it <- ifilterfalse(is_even, 1:10) as.list(it) # Similar idea here but anonymous function is used to filter out odd # numbers it2 <- ifilter(function(x) x %% 2 == 1, 1:10) as.list(it2) is_vowel <- function(x) { x %in% c('a', 'e', 'i', 'o', 'u') } it3 <- ifilterfalse(is_vowel, letters) iterators::nextElem(it3) # b iterators::nextElem(it3) # c iterators::nextElem(it3) # d iterators::nextElem(it3) # f iterators::nextElem(it3) # g # iterators::nextElem(it) continues through the rest of the consonants
# Filters out odd numbers and retains only even numbers is_even <- function(x) { x %% 2 == 0 } it <- ifilter(is_even, 1:10) as.list(it) # Similar idea here but anonymous function is used to filter out even # numbers it2 <- ifilter(function(x) x %% 2 == 1, 1:10) iterators::nextElem(it2) # 1 iterators::nextElem(it2) # 3 iterators::nextElem(it2) # 5 iterators::nextElem(it2) # 7 iterators::nextElem(it2) # 9 is_vowel <- function(x) { x %in% c('a', 'e', 'i', 'o', 'u') } it3 <- ifilter(is_vowel, letters) as.list(it3) # Filters out even numbers and retains only odd numbers is_even <- function(x) { x %% 2 == 0 } it <- ifilterfalse(is_even, 1:10) as.list(it) # Similar idea here but anonymous function is used to filter out odd # numbers it2 <- ifilter(function(x) x %% 2 == 1, 1:10) as.list(it2) is_vowel <- function(x) { x %in% c('a', 'e', 'i', 'o', 'u') } it3 <- ifilterfalse(is_vowel, letters) iterators::nextElem(it3) # b iterators::nextElem(it3) # c iterators::nextElem(it3) # d iterators::nextElem(it3) # f iterators::nextElem(it3) # g # iterators::nextElem(it) continues through the rest of the consonants
Counts the number of elements in an iterator. NOTE: The iterator is consumed in the process.
ilength(object)
ilength(object)
object |
an iterable object |
the number of elements in the iterator
ilength(1:5) == length(1:5) it <- iterators::iter(1:5) ilength(it) == length(1:5) it2 <- ichain(1:3, 4:5, 6) ilength(it2) it3 <- ichain(1:3, levels(iris$Species)) ilength(it3)
ilength(1:5) == length(1:5) it <- iterators::iter(1:5) ilength(it) == length(1:5) it2 <- ichain(1:3, 4:5, 6) ilength(it2) it3 <- ichain(1:3, levels(iris$Species)) ilength(it3)
Constructs an iterator that computes the given function f
using the
arguments from each of the iterables given in ...
.
imap(f, ...)
imap(f, ...)
f |
a function |
... |
multiple arguments to iterate through in sequence |
The iterator returned is exhausted when the shortest iterable in ...
is exhausted. Note that imap
does not recycle arguments as
Map
does.
The primary difference between istarmap
and
imap
is that the former expects an iterable object
whose elements are already grouped together, while the latter case groups the
arguments together before applying the given function. The choice is a matter
of style and convenience.
iterator that returns the values of object
along with the
index of the object.
pow <- function(x, y) { x^y } it <- imap(pow, c(2, 3, 10), c(5, 2, 3)) as.list(it) # Similar to the above, but because the second vector is exhausted after two # calls to `nextElem`, the iterator is exhausted. it2 <- imap(pow, c(2, 3, 10), c(5, 2)) as.list(it2) # Another similar example but with lists instead of vectors it3 <- imap(pow, list(2, 3, 10), list(5, 2, 3)) iterators::nextElem(it3) # 32 iterators::nextElem(it3) # 9 iterators::nextElem(it3) # 1000
pow <- function(x, y) { x^y } it <- imap(pow, c(2, 3, 10), c(5, 2, 3)) as.list(it) # Similar to the above, but because the second vector is exhausted after two # calls to `nextElem`, the iterator is exhausted. it2 <- imap(pow, c(2, 3, 10), c(5, 2)) as.list(it2) # Another similar example but with lists instead of vectors it3 <- imap(pow, list(2, 3, 10), list(5, 2, 3)) iterators::nextElem(it3) # 32 iterators::nextElem(it3) # 9 iterators::nextElem(it3) # 1000
Constructs an iterator that returns an iterable object
before padding
the iterator with the given fill
value indefinitely.
ipad(object, fill = NA)
ipad(object, fill = NA)
object |
an iterable object |
fill |
the value to pad the indefinite iterator after the initial
|
iterator that returns object
followed indefinitely by the
fill
value
it <- iterators::iter(1:9) it_ipad <- ipad(it) as.list(islice(it_ipad, end=9)) # Same as as.list(1:9) it2 <- iterators::iter(1:9) it2_ipad <- ipad(it2) as.list(islice(it2_ipad, end=10)) # Same as as.list(c(1:9, NA)) it3 <- iterators::iter(1:9) it3_ipad <- ipad(it3, fill=TRUE) as.list(islice(it3_ipad, end=10)) # Same as as.list(c(1:9, TRUE))
it <- iterators::iter(1:9) it_ipad <- ipad(it) as.list(islice(it_ipad, end=9)) # Same as as.list(1:9) it2 <- iterators::iter(1:9) it2_ipad <- ipad(it2) as.list(islice(it2_ipad, end=10)) # Same as as.list(c(1:9, NA)) it3 <- iterators::iter(1:9) it3_ipad <- ipad(it3, fill=TRUE) as.list(islice(it3_ipad, end=10)) # Same as as.list(c(1:9, TRUE))
Constructs an iterator of an iterable object
that returns its elements
in pairs.
ipairwise(object)
ipairwise(object)
object |
an iterable object |
an iterator that returns pairwise elements
it <- ipairwise(iterators::iter(letters[1:4])) iterators::nextElem(it) # list("a", "b") iterators::nextElem(it) # list("b", "c") iterators::nextElem(it) # list("c", "d") it2 <- ipairwise(1:5) iterators::nextElem(it2) # list(1, 2) iterators::nextElem(it2) # list(2, 3) iterators::nextElem(it2) # list(3, 4) iterators::nextElem(it2) # list(4, 5)
it <- ipairwise(iterators::iter(letters[1:4])) iterators::nextElem(it) # list("a", "b") iterators::nextElem(it) # list("b", "c") iterators::nextElem(it) # list("c", "d") it2 <- ipairwise(1:5) iterators::nextElem(it2) # list(1, 2) iterators::nextElem(it2) # list(2, 3) iterators::nextElem(it2) # list(3, 4) iterators::nextElem(it2) # list(4, 5)
Constructs an iterator generates all permutations of an iterable object. By
default, full-length permutations are generated. If m
is specified,
successive m
length permutations are instead generated.
ipermutations(object, m = NULL)
ipermutations(object, m = NULL)
object |
vector |
m |
length of permutations. By default, full-length permutations are generated. |
The implementation is loosely based on that of Python's itertools.
iterator that generates all permutations of object
it <- ipermutations(1:3) iterators::nextElem(it) # c(1, 2, 3) iterators::nextElem(it) # c(1, 3, 2) iterators::nextElem(it) # c(3, 1, 2) iterators::nextElem(it) # c(3, 2, 1) iterators::nextElem(it) # c(2, 3, 1) iterators::nextElem(it) # c(2, 1, 3) it2 <- ipermutations(letters[1:4]) # 24 = 4! permutations of the letters a, b, c, and d as.list(it2)
it <- ipermutations(1:3) iterators::nextElem(it) # c(1, 2, 3) iterators::nextElem(it) # c(1, 3, 2) iterators::nextElem(it) # c(3, 1, 2) iterators::nextElem(it) # c(3, 2, 1) iterators::nextElem(it) # c(2, 3, 1) iterators::nextElem(it) # c(2, 1, 3) it2 <- ipermutations(letters[1:4]) # 24 = 4! permutations of the letters a, b, c, and d as.list(it2)
Constructs an iterator that is the Cartesian product of each of the arguments.
iproduct(..., times = 1)
iproduct(..., times = 1)
... |
multiple arguments |
times |
the number of times the Cartesian product is repeated. By default, repeated only once. |
Although they share the same end goal, iproduct
can yield drastic
memory savings compared to expand.grid
.
iterator that iterates through each element from the Cartesian product
it <- iproduct(x=1:3, y=4:5) iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # Repeats the Cartesian product twice it <- iproduct(x=1:3, y=4:5, times=2) # First Cartesian product iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # Second Cartesian product iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # iproduct is a replacement for base::expand.grid() # Large data.frames are not created unless the iterator is manually consumed a <- 1:2 b <- 3:4 c <- 5:6 it3 <- iproduct(a=a, b=b, c=c) df_iproduct <- do.call(rbind, as.list(it3)) df_iproduct <- data.frame(df_iproduct) # Compare df_iproduct with the results from base::expand.grid() base::expand.grid(a=a, b=b, c=c)
it <- iproduct(x=1:3, y=4:5) iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # Repeats the Cartesian product twice it <- iproduct(x=1:3, y=4:5, times=2) # First Cartesian product iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # Second Cartesian product iterators::nextElem(it) # list(x=1, y=4) iterators::nextElem(it) # list(x=1, y=5) iterators::nextElem(it) # list(x=2, y=4) iterators::nextElem(it) # list(x=2, y=5) iterators::nextElem(it) # list(x=3, y=4) iterators::nextElem(it) # list(x=3, y=5) # iproduct is a replacement for base::expand.grid() # Large data.frames are not created unless the iterator is manually consumed a <- 1:2 b <- 3:4 c <- 5:6 it3 <- iproduct(a=a, b=b, c=c) df_iproduct <- do.call(rbind, as.list(it3)) df_iproduct <- data.frame(df_iproduct) # Compare df_iproduct with the results from base::expand.grid() base::expand.grid(a=a, b=b, c=c)
Constructs an iterator that replicates the values of an object
.
irep(object, times = 1, length.out = NULL, each = NULL) irep_len(object, length.out = NULL)
irep(object, times = 1, length.out = NULL, each = NULL) irep_len(object, length.out = NULL)
object |
object to return indefinitely. |
times |
the number of times to repeat each element in |
length.out |
non-negative integer. The desired length of the iterator |
each |
non-negative integer. Each element is repeated |
This function is intended an iterable version of the standard
rep
function. However, as exception, the recycling
behavior of rep
is intentionally not implemented.
iterator that returns object
it <- irep(1:3, 2) unlist(as.list(it)) == rep(1:3, 2) it2 <- irep(1:3, each=2) unlist(as.list(it2)) == rep(1:3, each=2) it3 <- irep(1:3, each=2, length.out=4) as.list(it3)
it <- irep(1:3, 2) unlist(as.list(it)) == rep(1:3, 2) it2 <- irep(1:3, each=2) unlist(as.list(it2)) == rep(1:3, each=2) it3 <- irep(1:3, each=2, length.out=4) as.list(it3)
Constructs an iterator that returns an object over and over again.
irepeat(object, times = NULL)
irepeat(object, times = NULL)
object |
object to return indefinitely. |
times |
the number of times |
Runs indefinitely unless the times
argument is specified. Used as
argument to imap
for invariant function
parameters. Also used with izip
to create constant
fields in a tuple record.
iterator that returns object
it <- irepeat(42) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) # Further calls to iterators::nextElem(it) will repeat 42 it2 <- irepeat(42, times=4) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) # The object can be a data.frame, matrix, etc it3 <- irepeat(iris, times=4) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3)
it <- irepeat(42) iterators::nextElem(it) iterators::nextElem(it) iterators::nextElem(it) # Further calls to iterators::nextElem(it) will repeat 42 it2 <- irepeat(42, times=4) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) iterators::nextElem(it2) # The object can be a data.frame, matrix, etc it3 <- irepeat(iris, times=4) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3) iterators::nextElem(it3)
Constructs an iterator that traverses each given iterable in a roundrobin order. That is, the iterables are traversed in an alternating fashion such that the each element is drawn from the next iterable. If an iterable has no more available elements, it is skipped, and the next element is taken from the next iterable having available elements.
iroundrobin(...)
iroundrobin(...)
... |
multiple arguments to iterate through in roundrobin sequence |
iterator that alternates through each argument in roundrobin sequence
it <- iterators::iter(c("A", "B", "C")) it2 <- iterators::iter("D") it3 <- iterators::iter(c("E", "F")) as.list(iroundrobin(it, it2, it3)) # A D E B F C it_rr <- iroundrobin(1:3, 4:5, 7:10) as.list(it_rr) # 1 4 7 2 5 8 3 9 10
it <- iterators::iter(c("A", "B", "C")) it2 <- iterators::iter("D") it3 <- iterators::iter(c("E", "F")) as.list(iroundrobin(it, it2, it3)) # A D E B F C it_rr <- iroundrobin(1:3, 4:5, 7:10) as.list(it_rr) # 1 4 7 2 5 8 3 9 10
Returns TRUE
if the object
is an object of class iter
,
and FALSE
otherwise.
is_iterator(object)
is_iterator(object)
object |
an R object |
logical value indicating whether object
is of class
iter
Constructs iterators that generate regular sequences that follow the
seq
family.
iseq(from = 1, to = 1, by = (to - from)/(length_out - 1), length_out = NULL, along_with = NULL) iseq_len(length_out = NULL) iseq_along(along_with = NULL)
iseq(from = 1, to = 1, by = (to - from)/(length_out - 1), length_out = NULL, along_with = NULL) iseq_len(length_out = NULL) iseq_along(along_with = NULL)
from |
the starting value of the sequence |
to |
the end value of the sequence |
by |
increment of the sequence. |
length_out |
desired length of the sequence. A non-negative number,
which for |
along_with |
the length of the sequence will match the length of this argument |
The iseq
function generates a sequence of values beginning with
from
and ending with to
. The sequence of values between are
determined by the by
, length_out
, and along_with
arguments. The by
argument determines the step size of the sequence,
whereas length_out
and along_with
determine the length of the
sequence. If by
is not given, then it is determined by either
length_out
or along_with
. By default, neither are given, in
which case by
is set to 1 or -1, depending on whether to >
from
.
seq_along
and seq_len
return an iterator, which generates a
sequence of integers, beginning with 1 and proceeding to an ending value
sequence's iterator
it <- iseq(from=2, to=5) unlist(as.list(it)) == 2:5 it2 <- iseq_len(4) unlist(as.list(it2)) == 1:4 it3 <- iseq_along(iris) unlist(as.list(it3)) == 1:length(iris)
it <- iseq(from=2, to=5) unlist(as.list(it)) == 2:5 it2 <- iseq_len(4) unlist(as.list(it2)) == 1:4 it3 <- iseq_along(iris) unlist(as.list(it3)) == 1:length(iris)
Constructs an iterator that returns elements from an iterable following the
given sequence with starting value start
and ending value end
.
The sequence's step size is given by step
.
islice(object, start = 1, end = NULL, step = 1)
islice(object, start = 1, end = NULL, step = 1)
object |
iterable object through which this function iterates |
start |
the index of the first element to return from |
end |
the index of the last element to return from |
step |
the step size of the sequence |
The iterable given in object
is traversed beginning with element
having index specified in start
. If start
is greater than 1,
then elements from the object
are skipped until start
is
reached. By default, elements are returned consecutively. However, if the
step
size is greater than 1, elements in object
are skipped.
If stop
is NULL
(default), the iteration continues until the
iterator is exhausted unless end
is specified. In this case,
end
specifies the sequence position to stop iteration.
iterator that returns object
in sequence
it <- islice(1:5, start=2) iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 4 iterators::nextElem(it) # 5 it2 <- islice(1:10, start=2, end=5) unlist(as.list(it2)) == 2:5 it3 <- islice(1:10, start=2, end=9, step=2) unlist(as.list(it3)) == c(2, 4, 6, 8)
it <- islice(1:5, start=2) iterators::nextElem(it) # 2 iterators::nextElem(it) # 3 iterators::nextElem(it) # 4 iterators::nextElem(it) # 5 it2 <- islice(1:10, start=2, end=5) unlist(as.list(it2)) == 2:5 it3 <- islice(1:10, start=2, end=9, step=2) unlist(as.list(it3)) == c(2, 4, 6, 8)
Constructs an iterator that applies the function f
concurrently to the
elements within the list x
.
istarmap(f, x) istar(f, x)
istarmap(f, x) istar(f, x)
f |
a function to apply to the elements of |
x |
an iterable object |
The iterator returned is exhausted when the shortest element in x
is exhausted. Note that istarmap
does not recycle arguments as
Map
does.
The primary difference between istarmap
and
imap
is that the former expects an iterable object
whose elements are already grouped together, while the latter case groups the
arguments together before applying the given function. The choice is a matter
of style and convenience.
iterator that returns the values of object
along with the
index of the object.
pow <- function(x, y) { x^y } it <- istarmap(pow, list(c(2, 3, 10), c(5, 2, 3))) unlist(as.list(it)) == c(32, 9, 1000) # Similar to the above, but because the second vector is exhausted after two # calls to `nextElem`, the iterator is exhausted. it2 <- istarmap(pow, list(c(2, 3, 10), c(5, 2))) unlist(as.list(it2)) == c(32, 9) # Another similar example but with lists instead of vectors it3 <- istarmap(pow, list(list(2, 3, 10), list(5, 2, 3))) as.list(it3) # Computes sum of each row in the iris data set # Numerically equivalent to base::rowSums() tolerance <- sqrt(.Machine$double.eps) iris_x <- iris[, -5] it4 <- istarmap(sum, iris_x) unlist(as.list(it4)) - rowSums(iris_x) < tolerance
pow <- function(x, y) { x^y } it <- istarmap(pow, list(c(2, 3, 10), c(5, 2, 3))) unlist(as.list(it)) == c(32, 9, 1000) # Similar to the above, but because the second vector is exhausted after two # calls to `nextElem`, the iterator is exhausted. it2 <- istarmap(pow, list(c(2, 3, 10), c(5, 2))) unlist(as.list(it2)) == c(32, 9) # Another similar example but with lists instead of vectors it3 <- istarmap(pow, list(list(2, 3, 10), list(5, 2, 3))) as.list(it3) # Computes sum of each row in the iris data set # Numerically equivalent to base::rowSums() tolerance <- sqrt(.Machine$double.eps) iris_x <- iris[, -5] it4 <- istarmap(sum, iris_x) unlist(as.list(it4)) - rowSums(iris_x) < tolerance
Constructs an iterator that maps a given function over an indefinite sequence
of numeric values. The input the function f
is expected to accept a
single numeric argument. The sequence of arguments passed to f
begin
with start
and are incremented by step
.
itabulate(f, start = 1, step = 1)
itabulate(f, start = 1, step = 1)
f |
the function to apply |
start |
sequence's initial value |
step |
sequence's step size |
an iterator that returns the mapped values from the sequence
it <- itabulate(f=function(x) x + 1) take(it, 4) # 2 3 4 5 it2 <- itabulate(f=function(x) x^2, start=-3) take(it2, 6) # 9 4 1 0 1 4 it3 <- itabulate(abs, start=-5, step=2) take(it3, 6) # 5 3 1 1 3 5 it4 <- itabulate(exp, start=6, step=-2) take(it4, 4) # exp(c(6, 4, 2, 0))
it <- itabulate(f=function(x) x + 1) take(it, 4) # 2 3 4 5 it2 <- itabulate(f=function(x) x^2, start=-3) take(it2, 6) # 9 4 1 0 1 4 it3 <- itabulate(abs, start=-5, step=2) take(it3, 6) # 5 3 1 1 3 5 it4 <- itabulate(exp, start=6, step=-2) take(it4, 4) # exp(c(6, 4, 2, 0))
Constructs an iterator that returns elements from an iterable object
as long as the given predicate
function returns TRUE
.
itakewhile(predicate, object)
itakewhile(predicate, object)
predicate |
a function that determines whether an element is |
object |
an iterable object |
iterator object
# Filters out numbers exceeding 5 not_too_large <- function(x) { x <= 5 } it <- itakewhile(not_too_large, 1:100) unlist(as.list(it)) == 1:5 # Same approach but uses an anonymous function it2 <- itakewhile(function(x) x <= 10, seq(2, 100, by=2)) unlist(as.list(it2)) == c(2, 4, 6, 8, 10)
# Filters out numbers exceeding 5 not_too_large <- function(x) { x <= 5 } it <- itakewhile(not_too_large, 1:100) unlist(as.list(it)) == 1:5 # Same approach but uses an anonymous function it2 <- itakewhile(function(x) x <= 10, seq(2, 100, by=2)) unlist(as.list(it2)) == c(2, 4, 6, 8, 10)
Constructs a list of n
iterators, each of which iterates through an
iterable object
.
itee(object, n = 2)
itee(object, n = 2)
object |
an iterable object |
n |
the number of iterables to return |
If the object
is an iterator (i.e., inherits from class iter
),
n
deep copies of object
are returned. Otherwise, object
is passed to iter
n
times.
a list of n
iterators
# Creates a list of three iterators. # Each iterator iterates through 1:5 independently. iter_list <- itee(1:5, n=3) # Consumes the first iterator unlist(as.list(iter_list[[1]])) == 1:5 # We can iterate through the remaining two iterators in any order. iterators::nextElem(iter_list[[2]]) # 1 iterators::nextElem(iter_list[[2]]) # 2 iterators::nextElem(iter_list[[3]]) # 1 iterators::nextElem(iter_list[[3]]) # 2 iterators::nextElem(iter_list[[2]]) # 3 iterators::nextElem(iter_list[[2]]) # 4 iterators::nextElem(iter_list[[2]]) # 5 iterators::nextElem(iter_list[[3]]) # 3 iterators::nextElem(iter_list[[3]]) # 4 iterators::nextElem(iter_list[[3]]) # 5
# Creates a list of three iterators. # Each iterator iterates through 1:5 independently. iter_list <- itee(1:5, n=3) # Consumes the first iterator unlist(as.list(iter_list[[1]])) == 1:5 # We can iterate through the remaining two iterators in any order. iterators::nextElem(iter_list[[2]]) # 1 iterators::nextElem(iter_list[[2]]) # 2 iterators::nextElem(iter_list[[3]]) # 1 iterators::nextElem(iter_list[[3]]) # 2 iterators::nextElem(iter_list[[2]]) # 3 iterators::nextElem(iter_list[[2]]) # 4 iterators::nextElem(iter_list[[2]]) # 5 iterators::nextElem(iter_list[[3]]) # 3 iterators::nextElem(iter_list[[3]]) # 4 iterators::nextElem(iter_list[[3]]) # 5
This function is useful when an iterator needs to be copied with a new
state
environment.
iter_deepcopy(iterator)
iter_deepcopy(iterator)
iterator |
an iterator object that inherits from class 'iter' |
a new iterator with its own state
Returns the length of an iterator object. In the case that the iterator's
length is NULL
, a value of 1 is returned by default. This value can be
set using the default
argument.
iter_length(object, default = 1)
iter_length(object, default = 1)
object |
an iterator object |
default |
the value returned when an iterator has |
integer
The R package itertools2
is a port of Python's excellent itertools
module https://docs.python.org/2/library/itertools.html to R for
efficient looping and is a replacement for the existing itertools R package
https://r-forge.r-project.org/projects/itertools/.
Constructs an iterator of an iterable object
that returns its elements
in pairs.
itripletwise(object)
itripletwise(object)
object |
an iterable object |
an iterator that returns tripletwise elements
it <- itripletwise(iterators::iter(letters[1:4])) iterators::nextElem(it) # list("a", "b", "c") iterators::nextElem(it) # list("b", "c", "d") it2 <- itripletwise(1:5) iterators::nextElem(it2) # list(1, 2, 3) iterators::nextElem(it2) # list(2, 3, 4) iterators::nextElem(it2) # list(3, 4, 5)
it <- itripletwise(iterators::iter(letters[1:4])) iterators::nextElem(it) # list("a", "b", "c") iterators::nextElem(it) # list("b", "c", "d") it2 <- itripletwise(1:5) iterators::nextElem(it2) # list(1, 2, 3) iterators::nextElem(it2) # list(2, 3, 4) iterators::nextElem(it2) # list(3, 4, 5)
Constructs an iterator that extracts each unique element in turn from an
iterable object
. Order of the elements is maintained. This function is
an iterator analogue to sort
.
iunique(object)
iunique(object)
object |
an iterable object |
NOTE: In order to determine whether an element is unique, a list of previous unique elements is stored. In doing so, the list can potentially become large if there are a large number of unique elements.
an iterator that returns the unique elements from object
it <- ichain(rep(1, 4), rep(2, 5), 4:7, 2) as.list(iunique(it)) # 1 2 4 5 6 7 it2 <- iterators::iter(c('a', 'a', "A", "V")) as.list(iunique(it2)) # a A V x <- as.character(gl(5, 10)) it_unique <- iunique(x) as.list(it_unique) # 1 2 3 4 5
it <- ichain(rep(1, 4), rep(2, 5), 4:7, 2) as.list(iunique(it)) # 1 2 4 5 6 7 it2 <- iterators::iter(c('a', 'a', "A", "V")) as.list(iunique(it2)) # a A V x <- as.character(gl(5, 10)) it_unique <- iunique(x) as.list(it_unique) # 1 2 3 4 5
Constructs an iterator that extracts each unique element in turn from an
iterable object
. Order of the elements is maintained. Only the element
just seen is remembered for determining uniqueness.
iunique_justseen(object)
iunique_justseen(object)
object |
an iterable object |
an iterator that returns the just-seen unique elements from
object
it <- ichain(rep(1,4), rep(2, 5), 4:7, 2) it_iunique <- iunique_justseen(it) as.list(it_iunique) # 1 2 4 5 6 7 2 it2 <- iterators::iter(c('a', 'a', "A", 'a', 'a', "V")) it2_iunique <- iunique_justseen(it2) as.list(it2_iunique) # a A a V
it <- ichain(rep(1,4), rep(2, 5), 4:7, 2) it_iunique <- iunique_justseen(it) as.list(it_iunique) # 1 2 4 5 6 7 2 it2 <- iterators::iter(c('a', 'a', "A", 'a', 'a', "V")) it2_iunique <- iunique_justseen(it2) as.list(it2_iunique) # a A a V
The resulting iterator aggregates elements from each of the iterables into a list from each iteration. Used for lock-step iteration over several iterables at a time.
izip(...)
izip(...)
... |
multiple arguments to iterate through in sequence |
iterator that iterates through each argument in sequence
it <- izip(x=1:3, y=4:6, z=7:9) iterators::nextElem(it) # list(x=1, y=4, z=7) iterators::nextElem(it) # list(x=2, y=5, z=8) iterators::nextElem(it) # list(x=3, y=6, z=9) # Sums the zip'd elements. 1 + 4 + 7, and so on. it2 <- izip(1:3, 4:6, 7:9) sum_zip <- sapply(it2, function(x) sum(unlist(x))) sum_zip == c(12, 15, 18) it3 <- izip(a=1:3, b=4:42, class=levels(iris$Species)) iterators::nextElem(it3) # list(a=1, b=4, class="setosa") iterators::nextElem(it3) # list(a=2, b=5, class="versicolor") iterators::nextElem(it3) # list(a=3, b=6, class="virginica")
it <- izip(x=1:3, y=4:6, z=7:9) iterators::nextElem(it) # list(x=1, y=4, z=7) iterators::nextElem(it) # list(x=2, y=5, z=8) iterators::nextElem(it) # list(x=3, y=6, z=9) # Sums the zip'd elements. 1 + 4 + 7, and so on. it2 <- izip(1:3, 4:6, 7:9) sum_zip <- sapply(it2, function(x) sum(unlist(x))) sum_zip == c(12, 15, 18) it3 <- izip(a=1:3, b=4:42, class=levels(iris$Species)) iterators::nextElem(it3) # list(a=1, b=4, class="setosa") iterators::nextElem(it3) # list(a=2, b=5, class="versicolor") iterators::nextElem(it3) # list(a=3, b=6, class="virginica")
The resulting iterator aggregates elements from each of the iterables into a list from each iteration. Used for lock-step iteration over several iterables at a time.
izip_longest(..., fill = NA)
izip_longest(..., fill = NA)
... |
multiple arguments to iterate through in sequence |
fill |
the value used to replace missing values when the iterables in
|
Although similar to izip
, missing values are
replaced with fill
if the iterables are of uneven length, and
Iteration continues until the longest iterable is exhausted.
iterator that iterates through each argument in sequence
it <- izip_longest(x=1:3, y=4:6, z=7:9) iterators::nextElem(it) # list(x=1, y=4, z=7) iterators::nextElem(it) # list(x=2, y=5, z=8) iterators::nextElem(it) # list(x=3, y=6, z=9) it2 <- izip_longest(1:3, 4:8) iterators::nextElem(it2) # list(1, 4) iterators::nextElem(it2) # list(2, 5) iterators::nextElem(it2) # list(3, 6) iterators::nextElem(it2) # list(NA, 7) iterators::nextElem(it2) # list(NA, 8) it3 <- izip_longest(1:2, 4:7, levels(iris$Species), fill="w00t") iterators::nextElem(it3) # list(1, 4, "setosa") iterators::nextElem(it3) # list(2, 5, "versicolor") iterators::nextElem(it3) # list("w00t", 6, "virginica") iterators::nextElem(it3) # list("w00t", 7, "w00t")
it <- izip_longest(x=1:3, y=4:6, z=7:9) iterators::nextElem(it) # list(x=1, y=4, z=7) iterators::nextElem(it) # list(x=2, y=5, z=8) iterators::nextElem(it) # list(x=3, y=6, z=9) it2 <- izip_longest(1:3, 4:8) iterators::nextElem(it2) # list(1, 4) iterators::nextElem(it2) # list(2, 5) iterators::nextElem(it2) # list(3, 6) iterators::nextElem(it2) # list(NA, 7) iterators::nextElem(it2) # list(NA, 8) it3 <- izip_longest(1:2, 4:7, levels(iris$Species), fill="w00t") iterators::nextElem(it3) # list(1, 4, "setosa") iterators::nextElem(it3) # list(2, 5, "versicolor") iterators::nextElem(it3) # list("w00t", 6, "virginica") iterators::nextElem(it3) # list("w00t", 7, "w00t")
Returns the n
th item of an iterator
after advancing the
iterator n
steps ahead. If the iterator
is entirely consumed,
the default
value is returned instead. That is, if either n >
length(iterator)
or n
is 0, then the iterator
is consumed.
nth(iterator, n, default = NA)
nth(iterator, n, default = NA)
iterator |
an iterator object |
n |
The location of the desired element to return |
default |
The value to return if iterable is consumed, default is NA |
The nth element of the iterable or the default value
it <- iterators::iter(1:10) # Returns 5 nth(it, 5) it2 <- iterators::iter(letters) # Returns 'e' nth(it2, 5) it3 <- iterators::iter(letters) # Returns default value of NA nth(it3, 42) it4 <- iterators::iter(letters) # Returns default value of "foo" nth(it4, 42, default="foo")
it <- iterators::iter(1:10) # Returns 5 nth(it, 5) it2 <- iterators::iter(letters) # Returns 'e' nth(it2, 5) it3 <- iterators::iter(letters) # Returns default value of NA nth(it3, 42) it4 <- iterators::iter(letters) # Returns default value of "foo" nth(it4, 42, default="foo")
Returns the number of elements from an iterable object evaluate to
TRUE
.
quantify(object)
quantify(object)
object |
an iterable object |
the number of TRUE
elements
it <- iterators::iter(c(TRUE, FALSE, TRUE)) quantify(it) # 2 set.seed(42) x <- sample(c(TRUE, FALSE), size=10, replace=TRUE) quantify(x) # Equivalent to sum(x)
it <- iterators::iter(c(TRUE, FALSE, TRUE)) quantify(it) # 2 set.seed(42) x <- sample(c(TRUE, FALSE), size=10, replace=TRUE) quantify(x) # Equivalent to sum(x)
Returns TRUE
if the object
resulted from a StopIteration
exception when nextElem
is called, and FALSE
otherwise.
stop_iteration(object)
stop_iteration(object)
object |
an R object |
TRUE
if object
resulted from a StopIteration
exception. Otherwise, FALSE
.
Returns the first n
elements of an iterable object
as a list.
If n
is larger than the number of elements in object
, the
entire iterator is consumed.
take(object, n = 1)
take(object, n = 1)
object |
an iterable object |
n |
the number of elements to return in the list |
a list of the first n
items of the iterable object
take(iterators::iter(1:10), 3) # 1 2 3 take(iterators::iter(1:5), 10) # 1 2 3 4 5
take(iterators::iter(1:10), 3) # 1 2 3 take(iterators::iter(1:5), 10) # 1 2 3 4 5
Returns the next element of object
. In the case a StopIteration
exception is thrown, the default
value is returned instead.
try_nextElem(object, default = NA, silent = TRUE)
try_nextElem(object, default = NA, silent = TRUE)
object |
an iterable object |
default |
default value returned if a StopIteration exception is thrown |
silent |
Should any errors be suppressed without explicitly notifying the user? Default. Yes |
the next element of object