| title | format |
|---|---|
Merging R objects like dictionaries in R |
html |
Let's explore how to merge lists, enviroments or vectors like dictionaries in R.
pak::pak(c(
"purrr",
"rlang",
"bench",
"flextable",
"dplyr",
"fastmap",
"collections"
))
I have this:
context <- list("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
I would like this output:
#$language
#[1] "en"
#
#$timezone
#[1] "UTC"
#
#$breadcrumbs
#[1] "Home"
#
#$title
#[1] "Home"
What functions can I use?
list_base_modify <- \() {
context <- list("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
result <- context |>
modifyList(more_context)
result
}
list_base_modify()
list_tidyverse_modify <- \() {
context <- list("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
result <- context |>
purrr::list_modify(!!!more_context)
result
}
list_tidyverse_modify()
library(fastmap)
list_fastmap_set <- \() {
context <- list("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
m <- fastmap()
m$mset(.list = context)
m$mset(.list = more_context)
m$as_list()
}
list_fastmap_set()
library(collections)
list_collections_dict_update <- \() {
context <- list("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
d <- dict(context)
d$update(dict(more_context))
d$as_list()
}
list_collections_dict_update()
For enviroments, I would like this output:
#$language
#[1] "en"
#
#$timezone
#[1] "UTC"
#
#$breadcrumbs
#[1] "Home"
#
#$title
#[1] "Home"
library(rlang)
env_rlang_list2env <- \() {
context <- list2env(list(
"language" = "en",
"timezone" = "UTC",
"breadcrumbs" = "None"
))
more_context <- list("title" = "Home", "breadcrumbs" = "Home")
env_bind(context, !!!more_context)
result <- as.list(context)
result
}
env_rlang_list2env()
I have this:
context <- c("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- c("title" = "Home", "breadcrumbs" = "Home")
I would like this output:
# language timezone title breadcrumbs
# "en" "UTC" "Home" "Home"
What functions can I use?
vectors_base_names <- \() {
context <- c("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- c("title" = "Home", "breadcrumbs" = "Home")
context[names(more_context)] <- more_context
context
}
vectors_base_names()
vectors_tidyverse_names <- \() {
context <- c("language" = "en", "timezone" = "UTC", "breadcrumbs" = "None")
more_context <- c("title" = "Home", "breadcrumbs" = "Home")
result <- context |>
purrr::discard_at(names(more_context)) |>
c(more_context)
result
}
vectors_tidyverse_names()
library(bench)
library(flextable)
library(dplyr)
results <- bench::mark(
iterations = 10000,
check = FALSE,
list_base_modify(),
list_tidyverse_modify(),
list_fastmap_set(),
list_collections_dict_update(),
env_rlang_list2env(),
vectors_base_names(),
vectors_tidyverse_names()
)
ranking <- results |>
select(expression, median, `itr/sec`) |>
mutate(expression = as.character(expression)) |>
arrange(desc(`itr/sec`))
ranking$faster <- as.double(ranking$median[[nrow(ranking)]] / ranking$median)
ranking
ranking |>
flextable() |>
colformat_double(j = "faster", digits = 2)
It seems like using base vectors are the fastest of the explored options to merge like dictionaries in R. 15 times faster than purrr::list_modify, fastmap or collections::dict
# A tibble: 7 × 4 expression median `itr/sec` faster 1 vectors_base_names() 1.44µs 659799. 15.8 2 list_base_modify() 5.39µs 177834. 4.22 3 env_rlang_list2env() 6.66µs 144925. 3.42 4 list_collections_dict_update() 19.95µs 49000. 1.14 5 vectors_tidyverse_names() 20.66µs 45073. 1.10 6 list_tidyverse_modify() 21.5µs 45050. 1.06 7 list_fastmap_set() 22.76µs 42821. 1