Skip to content

Instantly share code, notes, and snippets.

@coolbutuseless
Last active October 2, 2018 13:35
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 coolbutuseless/74a763c95fb603a9cfbf328f51dae883 to your computer and use it in GitHub Desktop.
Save coolbutuseless/74a763c95fb603a9cfbf328f51dae883 to your computer and use it in GitHub Desktop.
alternatives to nested for loops
check <- function(dog, location) { cat("Checking for", dog, "in", location, "\n") }
dogs <- c('poodle', 'greyhound', 'mutt')
locations <- c('park', 'street', 'yard')
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Nested for-loop
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (dog in dogs) {
for (location in locations) {
check(dog, location)
}
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Expand grid + pwalk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
expand.grid(dog=dogs, location=locations, stringsAsFactors = FALSE) %>%
pwalk(check)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# nested walk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
walk(locations, ~walk(dogs, check, .x))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# cross2 + pwalk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cross2(dogs, locations) %>%
transpose() %>%
pwalk(check)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# cross2 + walk. v2
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cross2(dogs, locations) %>%
walk(~check(dog=.x[[1]], location=.x[[2]]))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Cross + explicit names + walk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cross(list(dog=dogs, location=locations)) %>%
walk(~check(dog=.x$dog, location=.x$location))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using cross() instead of cross2() for explicit naming
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cross(list(dog=dogs, location=locations)) %>%
transpose() %>%
pwalk(check)
@MilesMcBain
Copy link

If you're not looking for a side effect, and can live without the formula interface you have some base options too:

check <- function(dog, location) { paste("Checking for", dog, "in", location, "\n")}
dogs      <- c('poodle', 'greyhound', 'mutt')
locations <- c('park', 'street', 'yard')

cat(outer(dogs, locations, check))
cat(kronecker(dogs, locations, check))

I do use outer() from time to time myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment