pull all elements with specific name from a nested list

后端 未结 4 1890
谎友^
谎友^ 2021-01-16 13:38

I have some archived Slack data that I am trying to get some of key message properties. I\'d done this by stupidly flattening the entire list, getting a data.frame or tibble

相关标签:
4条回答
  • 2021-01-16 13:55

    Depending on the desired output, I would probably use a simple recursive function here.

    get_elements <- function(x, element) {
      if(is.list(x))
      {
        if(element %in% names(x)) x[[element]]
        else lapply(x, get_elements, element = element)
      }
    }
    

    This allows:

    get_elements(l, "type")
    #> $folder_1
    #> $folder_1$`msg_1-1`
    #> [1] "message"
    #> 
    #> $folder_1$`msg_1-2`
    #> [1] "message"
    #> 
    #> 
    #> $folder_2
    #> $folder_2$`msg_2-1`
    #> [1] "message"
    

    Or if you want to get all "users":

    get_elements(l, "user")
    #> $folder_1
    #> $folder_1$`msg_1-1`
    #> [1] "UFUNNF8MA"
    #> 
    #> $folder_1$`msg_1-2`
    #> [1] "UNFUNQ8MA"
    #> 
    #> 
    #> $folder_2
    #> $folder_2$`msg_2-1`
    #> [1] "UQKUNF8MA"
    

    You could obviously unlist the result if you prefer it flattened into a vector.

    unlist(get_elements(l, "type"))
    #> folder_1.msg_1-1 folder_1.msg_1-2 folder_2.msg_2-1 
    #>        "message"        "message"        "message" 
    
    0 讨论(0)
  • 2021-01-16 14:18

    As OP mentioned, this can solve the issue:

    #Code
    unlist(l)[grepl('.type',names(unlist(l)),fixed=T)]
    

    Output:

    folder_1.msg_1-1.type folder_1.msg_1-2.type folder_2.msg_2-1.type 
                "message"             "message"             "message" 
    

    Another options are (Many thanks and credit to @Abdessabour Mtk)

    #Code1
    purrr::map(l, ~ purrr::map(.x, "type"))
    
    0 讨论(0)
  • 2021-01-16 14:19

    Related to those provided by @Duck & @Abdessabour Mtk yesterday, purrr has a function map_depth() that will let you get a named attribute if you know its name and how deep it is in the hierarchy. REALLY useful when crawling this big nested lists, and is a simpler solution to the nested map() calls above.

    purrr::map_depth(l, 2, "type")
    
    0 讨论(0)
  • 2021-01-16 14:21

    Another option is to use rrapply() in the rrapply-package:

    library(rrapply)
    
    ## return unlisted vector
    rrapply(l, condition = function(x, .xname) .xname == "type", how = "unlist")
    #> folder_1.msg_1-1.type folder_1.msg_1-2.type folder_2.msg_2-1.type 
    #>             "message"             "message"             "message"
    
    ## return melted data.frame
    rrapply(l, condition = function(x, .xname) .xname == "type", how = "melt")
    #>         L1      L2   L3   value
    #> 1 folder_1 msg_1-1 type message
    #> 2 folder_1 msg_1-2 type message
    #> 3 folder_2 msg_2-1 type message
    
    0 讨论(0)
提交回复
热议问题