Skip to content

Instantly share code, notes, and snippets.

@mllg
Created November 14, 2013 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mllg/7469844 to your computer and use it in GitHub Desktop.
Save mllg/7469844 to your computer and use it in GitHub Desktop.
Simple iterator for the Cartesian product
cart_iter = function(li) {
nextState = function(state, pos = 1L) {
if (state[pos] < state.last[pos])
replace(state, pos, state[pos] + 1L)
else
nextState(replace(state, pos, 1L), pos + 1L)
}
nextElem = function() {
state <<- nextState(state)
counter <<- counter + 1L
mapply(function(i, j) li[[i]][j], i=names(state), j=state)
}
hasNext = function() {
counter < counter.max
}
reset = function() {
state <<- state.init
counter <<- 0L
invisible(TRUE)
}
state.last = sort(vapply(li, length, 1L), decreasing=TRUE)
state.init = setNames(c(0L, rep.int(1L, length(state.last) - 1L)), names(state.last))
counter.max = prod(state.last)
if (counter.max > .Machine$integer.max)
stop("The generated design is too big. Designs with up to ",
.Machine$integer.max, " rows are supported!")
counter.max = as.integer(counter.max)
state = state.init
counter = 0L
list(nextElem = nextElem,
hasNext = hasNext,
reset = reset,
n.states = counter.max)
}
it = cart_iter(list(x = 1:10, b = 1:2))
while(it$hasNext()) {
print(it$nextElem())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment