3

How can I check if an element of list exists or not. This is a list of lists so for example I want to check whether the third element l1[[3]] exists or not. I have tried is.null(l1[["3"]]) but it returns false no matter whether it exists or not and if I use is.null(l1[[3]]) it will give the error of subscript out of bind in case it does not exists but not TRUE. How should I che

hora
  • 845
  • 5
  • 14
  • 25

3 Answers3

6

tl;dr: If you want to check if element n exists, even if checking at end of a list or an empty list, use:

length(mylist) >= n   # TRUE indicates exists. FALSE indicates DNE

For nested lists, make sure to check the correct list. eg:

 length(outerlist[[innerlist]]) >= n




NULL in lists in R has some differences from what one is used to in other languages. For example, if we replace the element of a list by NULL, all subsequent elements are shifted over, and the list is left with a length of one less.
# SAMPLE DATA
mylist <- as.list(LETTERS[1:5])

    [[1]]
    [1] "A"

    [[2]]
    [1] "B"

    [[3]]
    [1] "C"

    [[4]]
    [1] "D"

    [[5]]
    [1] "E"

Testing for NULL in elements 3 & 6. Not quite the information we are looking for.

is.null(mylist[[3]])
# FALSE

is.null(mylist[[6]])
# Error in mylist[[6]] : subscript out of bounds

Instead we check the length of the list:

length(mylist) >= 3  # TRUE
length(mylist) >= 5  # TRUE
length(mylist) >= 6  # FALSE

Removing the 3rd element. Notice that the "empty slot" is not preserved. (ie, element 4, becomes element 3, etc..)

mylist[[3]] <- NULL

  [[1]]
  [1] "A"

  [[2]]
  [1] "B"

  [[3]]
  [1] "D"

  [[4]]
  [1] "E"


length(mylist) >= 3  # TRUE
length(mylist) >= 5  # FALSE
length(mylist) >= 6  # FALSE

An empty list will have length of 0

emptyList <- list()
length(emptyList)  # 0

nestedList <- list( letters=list("A", "B", "C"), empty=list(), words=list("Hello", "World"))

length(nestedList)
  # [1] 3
lapply(nestedList, length)
  # $letters
  # [1] 3
  #
  # $empty
  # [1] 0
  #
  # $words
  # [1] 2



Note that you can incoporate NULL into a list. Which is when testing for NULL is applicable. For example:
myListWithNull <- list("A", "B", NULL, "D")

is.null(myListWithNull[[3]])
  # TRUE

length(myListWithNull) >= 3
  # TRUE
Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
  • this is useful but I think you might spell out the implications for the OP (who might be an R newbie) a bit more. In particular it doesn't really answer the question (how do I tell if element 3 of a list exists?) – Ben Bolker Dec 07 '12 at 14:55
  • It also might be the last element of the list which I do not know whether it exists or not. How can I check its existence? – hora Dec 07 '12 at 15:01
  • @hora, part of the issue might be in how one defines "exists". How specifically do you mean? What would be an example of it existing, what would be an example of non-existence? – Ricardo Saporta Dec 07 '12 at 15:02
  • For example in your sample, how do you check whether the sixth element exists or not? – hora Dec 07 '12 at 15:05
  • by using `length()`. If the length is `>= 6` then the 6th element exists else it does not. In my example, note the difference when checking for the 5th element before and after removing one element. – Ricardo Saporta Dec 07 '12 at 15:06
  • @hora, please see revisions in answer above – Ricardo Saporta Dec 07 '12 at 15:13
  • yes. Finally I got it. Sorry I feel like some how stupid now :))) – hora Dec 07 '12 at 15:15
1

As I posted here, rather than checking the length of the whole list, it's possible to check the length of the element itself to check for NULL values. As far as I can tell, all values except NULL have a length greater than 0.

x <- list(4, -1, NULL, NA, Inf, -Inf, NaN, T, x = 0, y = "", z = c(1,2,3))
lapply(x, function(el) print(length(el)))
[1] 1
[1] 1
[1] 0
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 3

Thus we could make a simple function that works with both named and numbered indices:

element.exists <- function(var, element)
{
  tryCatch({
    if(length(var[[element]]) > -1)
      return(T)
  }, error = function(e) {
    return(F)
  })
}

If the element doesn't exist, it causes an out-of-bounds condition caught by the tryCatch block.

1

As evaluation of statements in if stops as soon as a condition is false, you can use the following to reliably check if an element is empty:

if(length(l1)<n || is.null(l1[[n]]){ # TRUE only if not NULL
}

Alternatively you can use named lists

is.null(l1[["a"]])

behaves independently from the length of the list.

cmbarbu
  • 4,354
  • 25
  • 45