Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pull all elements with specific name from a nested list

Tags:

r

purrr

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 with lists nested in some cells. As this dataset gets bigger, I want to pick elements out of this list more smartly so that when this cache becomes big it doesn't take forever to create the data.frame or tibble with the elements I want.

Example where I am trying to pull everything named "type" below into a vector or flat list that I can pull in as a dataframe variable. I named the folder and message level for convenience. Anyone have model code that can help?

library(tidyverse)
    
l <- list(folder_1 = list(
  `msg_1-1` = list(type = "message",
               subtype = "channel_join",
               ts = "1585771048.000200",
               user = "UFUNNF8MA",
               text = "<@UFUNNF8MA> has joined the channel"),
  `msg_1-2` = list(type = "message",
                   subtype = "channel_purpose",
                   ts = "1585771049.000300",
                   user = "UNFUNQ8MA",
                   text = "<@UNFUNQ8MA> set the channel purpose: Talk about xyz")),
  folder_2 = list(
    `msg_2-1` = list(type = "message",
                  subtype = "channel_join",
                  ts = "1585771120.000200",
                  user = "UQKUNF8MA",
                  text = "<@UQKUNF8MA> has joined the channel")) 
)

# gets a specific element
print(l[[1]][[1]][["type"]])

# tried to get all elements named "type", but am not at the right list level to do so
print(purrr::map(l, "type"))
like image 519
M. Wood Avatar asked Jul 20 '26 10:07

M. Wood


1 Answers

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" 
like image 108
Allan Cameron Avatar answered Jul 23 '26 03:07

Allan Cameron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!