Dihan
Dihan

Reputation: 311

alternative of for loop in R


cell_support_xyz <- function(level, zero)
{
  for(i in 1:level[1]){
    for(j in 1:level[2]){
      for(k in 1:level[3]){
        cat("cell (", i, ", ", j, ", ", k,") --> support set = (", 
            +!(i == zero[1]), ", ", +!(j == zero[2]), ", ", +!(k == zero[3]), ")\n", sep = "")
        
      }      
    }
  }
}


#Example 1
l<-c(2,3,2)
z<-c(1,1,1)
> cell_support_xyz(l,z)

cell (1, 1, 1) --> support set = (0, 0, 0)
cell (1, 1, 2) --> support set = (0, 0, 1)
cell (1, 2, 1) --> support set = (0, 1, 0)
cell (1, 2, 2) --> support set = (0, 1, 1)
cell (1, 3, 1) --> support set = (0, 1, 0)
cell (1, 3, 2) --> support set = (0, 1, 1)
cell (2, 1, 1) --> support set = (1, 0, 0)
cell (2, 1, 2) --> support set = (1, 0, 1)
cell (2, 2, 1) --> support set = (1, 1, 0)
cell (2, 2, 2) --> support set = (1, 1, 1)
cell (2, 3, 1) --> support set = (1, 1, 0)
cell (2, 3, 2) --> support set = (1, 1, 1)

The above code works just fine. But I want to avoid for loop. Here I used 3 for loops (because the length of both argument vectors is 3). If the length of vectors increases or decreases the function won't work (I need to adjust for loops accordingly); which is why I want to replace for-loop with some efficient alternative that works for any length. Any suggestion?

Upvotes: 0

Views: 130

Answers (2)

Alexlok
Alexlok

Reputation: 3134

You can do that in 2 steps:

l<-c(2,3,2)
z<-c(1,1,1)

cells <- expand.grid(lapply(l, seq))

t(apply(cells, 1, function(x) 1L*!(x == z)))

cells contains all the combinations. If the order matters, you can simply reorder it:

cells <- dplyr::arrange(cells, Var1, Var2, Var3)

Then, for each row (apply(,1,)) you can use == which is already vectorized to compare the entire row to the entire z vector.

Multiplying by 1L makes it integer, same as +.

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 388797

One way to remove the for loop and making the solution flexible enough for any length input.

We use expand.grid to create all possible combinations of level and use apply rowwise to create a string to print.

cell_support_xyz <- function(level, zero) {
  tmp <- do.call(expand.grid, lapply(level, seq))
  abc <- apply(tmp, 1, function(x) 
               cat(sprintf('cell (%s) --> support set = (%s)\n', 
                   toString(x), toString(+(x != zero)))))
}

l<-c(2,3,2)
z<-c(1,1,1)

cell_support_xyz(l, z)
#cell (1, 1, 1) --> support set = (0, 0, 0)
#cell (2, 1, 1) --> support set = (1, 0, 0)
#cell (1, 2, 1) --> support set = (0, 1, 0)
#cell (2, 2, 1) --> support set = (1, 1, 0)
#cell (1, 3, 1) --> support set = (0, 1, 0)
#cell (2, 3, 1) --> support set = (1, 1, 0)
#cell (1, 1, 2) --> support set = (0, 0, 1)
#cell (2, 1, 2) --> support set = (1, 0, 1)
#cell (1, 2, 2) --> support set = (0, 1, 1)
#cell (2, 2, 2) --> support set = (1, 1, 1)
#cell (1, 3, 2) --> support set = (0, 1, 1)
#cell (2, 3, 2) --> support set = (1, 1, 1)

Upvotes: 2

Related Questions