0

Looking at this question it is possible to test if an element of a list exists, provided your list has names:

foo <- list(a=1)
"a" %in% names(list)  # TRUE
"b" %in% names(list)  # FALSE

However it is not clear if or how this can be extended to a list which isn't named:

foo <- list(1)
names(list)    # NULL

I can test this using tryCatch but it isn't particularly elegant:

indexExists <- function(list, index) {
  tryCatch({
    list[[index]]  # Efficiency if element does exist and is large??
    TRUE
  }, error = function(e) {
    FALSE
  })
}

Is there a better way of going about this?

Community
  • 1
  • 1
Scott Ritchie
  • 10,293
  • 3
  • 28
  • 64
  • 3
    If a list doesn't have names, then your question isn't well-defined in the first place. – Hong Ooi Oct 07 '13 at 05:44
  • I agree with @HongOoi - If you think you have a legitimate question could you provide some more example inputs and their corresponding outputs? – Dason Oct 07 '13 at 05:45
  • I'm not sure why you consider it ill-defined in that case? Suppose it is meaningless to assign names to my list, and I'm just using numeric indices? Specifically I came across the problem throwing an answer together for this question: http://stackoverflow.com/questions/19215082/plot-rows-of-numbers-that-fall-within-a-defined-proximity-to-other-rows-in-r – Scott Ritchie Oct 07 '13 at 05:48
  • 2
    If you only have numeric indices, then `length(lst)` tells you straight away all the information you have. Not sure what you're trying to do. – Hong Ooi Oct 07 '13 at 06:00
  • ^ I knew there was an obvious answer that I was missing :) – Scott Ritchie Oct 07 '13 at 06:09

1 Answers1

0

Hong Ooi's answer works for one dimension, but I thought I would add an answer that works for multiple dimension indices.

indexExists <- function(ind, form) {
    if (ind[[1]] > length(form) || ind[[1]] < 1)
        return(FALSE)
    dim <- 1
    while (dim + 1 <= length(ind)) {
        if (ind[dim + 1] > length(form[[ ind[1:dim] ]] ) || ind[dim + 1] < 1)
            return(FALSE)
        dim <- dim + 1
    }
    return(TRUE)
}

Here is some sample output:

> aList <- list( list(1,2,list(1,10,100,1000),3), 5 )
> indexExists(c(1), aList)
[1] TRUE
> indexExists(c(2), aList)
[1] TRUE
> indexExists(c(0), aList)
[1] FALSE
> indexExists(c(3), aList)
[1] FALSE
> indexExists(c(1,1), aList)
[1] TRUE
> indexExists(c(1,3), aList)
[1] TRUE
> indexExists(c(1,4), aList)
[1] TRUE
> indexExists(c(1,0), aList)
[1] FALSE
> indexExists(c(1,5), aList)
[1] FALSE
> indexExists(c(1,3,4), aList)
[1] TRUE
> indexExists(c(1,3,5), aList)
[1] FALSE

Note that I don't think the efficiency of the answer in your question depends on the size of the list elements because in this case R will only create a new object in memory if you modify the copied object. I might suggests assigning list[[index]] though (this makes it clear that you're assigning and not e.g. printing).

scottkosty
  • 2,410
  • 1
  • 16
  • 22