'Allow R double (nested) For Loop to run when one of the loops has NULL values

Suppose I have a double For Loop with 2 values each giving 2x2=4 loops.

p_vals = c(1,2)
q_vals = c(3,4)

for (p in p_vals) {
  for (q in q_vals) {
    
    paste(p,q) |> print()      
    
  }
}

[1] "1 3"
[1] "1 4"
[1] "2 3"
[1] "2 4"

Then suppose I want to control p_vals and q_vals upstream such that sometimes they may be NULL, in which case I'd expect the double-loop to run as a single loop. For example:

p_vals = c(1,2)
q_vals = NULL

for (p in p_vals) {
  for (q in q_vals) {
    
    paste(p,q) |> print()        
    
  }
}

I'd expect the above to produce

[1] "1 "
[1] "2 "

But it doesn't produce anything at all.



Solution 1:[1]

If you can really control the flow upstream, it might be better to use an NA instead of a NULL. The reason being the length of the vector.

> length(NULL)
[1] 0
> length(NA)
[1] 1

So now the loop will run once with an NA (i.e., no loop) and within the inner loop you can control the behavior of the NA based on your problem. Of course, if you need the NAs to have another meaning, you would have to find another way or value that you can reserve.

p_vals = c(1,2)
q_vals = NA

for (p in p_vals) {
  for (q in q_vals) {
    
    if (is.na(p)) p <- ""
    if (is.na(q)) q <- ""
    
    paste(p,q) |> print()      
    
  }
}
# [1] "1 "
# [1] "2 "

Edit

You can also do something like this to make the NULL have a length of 1 in the loop to run once, and then reference the p_vals and q_vals from the index. Maybe this is more natural for your use case.

p_vals = c(1,2)
q_vals = NULL

null_seq <- function(x) if(is.null(x)) 1 else seq_along(x)

for (p in null_seq(p_vals)) {
  for (q in null_seq(q_vals)) {
    
    paste(p_vals[p], q_vals[q]) %>% print()        
    
  }
}
# [1] "1 "
# [1] "2 "

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1