R Question

How to avoid storing null values when I skip an iteration in a for loop? [R]

Exist a way to avoiding to store null values in an iterative process when some condition is activated to skip to the next iteration? The intention of "how to solve" this problem is with the structure itself of the loop

[CONTEXT]:

I refer to the case when you need to use a storing mechanism inside a loop in conjunction with a conditional statement, and it is given the scenario where basically one of the possibles path is not of your interest. In the honor to give the treatment in the moment, and not posterior of the computation, you skip to the next iteration.

[EXAMPLE]

Suppose given a certain sequence of numbers, I interested only in stored the numbers of the sequence that are greater than 2 in a list.

storeGreaterThan2 <- function(x){
y <- list()
for (i in seq_along(x)) {
if (x[i] > 2) {
y[[i]] <- x[i]
} else {
next
}
}
y
}


The previous function deal with the final purpose, but when the condition to skip the iteration is activated the missing operation in the index is filled with a null value in the final list.

> storeGeaterThan2(1:5)
[[1]]
NULL

[[2]]
NULL

[[3]]
[1] 3

[[4]]
[1] 4

[[5]]
[1] 5


In the spirit of dealing with the problem inside the structure of the loop, how it could deal with that?

Answer

This is a rather strange example, and I wonder if it's an x-y problem. It may be better to say more about your situation and what you ultimately want to do. For example, there are different ways of trying to do this depending on if the function's input will always be an ascending sequence. @Dave2e's comment that there will be better ways depending of what you are really after is right on the mark, in my opinion. At any rate, you can simply removed the NULL elements before you return the list. Consider:

storeGreaterThan2 <- function(x){
  y <- list()
    for(i in seq_along(x)) {
      if(x[i] > 2) {
        y[[i]] <- x[i]
      } else {
        next
      }
    }
  y <- y[-which(sapply(y, is.null))]
  return(y)
}
storeGreaterThan2(1:5)
# [[1]]
# [1] 3
# 
# [[2]]
# [1] 4
# 
# [[3]]
# [1] 5

Here is a possible way to do this without ever having stored the NULL element, rather than cleaning it up at the end:

storeGreaterThan2 <- function(x){
  y <- list()
  l <- 1                   # l is an index for the list
  for(i in seq_along(x)){  # i is an index for the x vector
    if(x[i] > 2) {
      y[[l]] <- x[i]
      l      <- l+1
    } 
  }
  return(y)
}
Comments