Search code examples
rlisthttr

Structure of large list


Here's a reproducible example:

a <- list(list(LETTERS[1:3],LETTERS[1:3]),list(LETTERS[4:6]))
a
# [[1]]
# [[1]][[1]]
# [1] "A" "B" "C"
# 
# [[1]][[2]]
# [1] "A" "B" "C"
# 
# [[2]]
# [[2]][[1]]
# [1] "D" "E" "F"

Can someone explain the logic behind the list numbering?

I have a very large list of lists...(223 deep), example 5 deep:

[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[[1]][[1]][[1]][[1]]
[[1]][[1]][[1]][[1]][[1]]
list()

[[1]][[1]][[1]][[1]][[2]]
[[1]][[1]][[1]][[1]][[2]][[1]]
Response [https://api.livechatinc.com/v2/chats?/date_from=2014-03-22&page=1]
Date: 2015-03-20 15:41
Status: 200
Content-Type: application/json; charset=utf-8
Size: 166 kB

down to:

[[2]]
[[2]][[1]]
Response [https://api.livechatinc.com/v2/chats?/date_from=2014-03-22&page=5]
Date: 2015-03-20 15:41
Status: 200
Content-Type: application/json; charset=utf-8
Size: 133 kB

And wish to extract content using httr's content function. Using lapply returns: Error: is.response(x) is not TRUE

The only way I know to access each is to call each list directly:

content(listName[[1]][[2]][[1]])

Any suggestions how I can call the function content on each one?

I tried content within rapply and also unlist, then content with no change in error message.


Solution

  • Here's an example structure that sounds sort of like yours:

    library("httr")
    u <- "http://www.google.com"
    g <- GET(u)
    a <- list()
    a[[1]] <- g
    a[[2]] <- list(g, g)
    a[[3]] <- list(g, list(g))
    a[[4]] <- list(list(g, list(list(g, g))))
    str(a, 1)
    # List of 4
    #  $ :List of 9
    #   ..- attr(*, "class")= chr "response"
    #  $ :List of 2
    #  $ :List of 2
    #  $ :List of 1
    

    You can write a function that either extracts the contents of the request or, if inapplicable, tries to recursively extract contents from nodes lower on the list tree. Then lapply that function to your list:

    extract <- function(x) {
        if(inherits(x, "response")) {
            return(content(x))
        } else if(length(x)){
            lapply(x, extract) # apply `extract` recursively
        }
    }
    
    out <- unlist(lapply(a, extract))
    

    Result is a list of extracted contents:

    str(out)
    # List of 8
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr> 
    #  $ :Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument' <externalptr>