Starting from init_list
or list_clustered_by_name
I want to arrive to desired_list
.
I wonder if there is a better procedure, than the one I developed, here:
Maybe something with map_if, checking length, but I couldn't.
library(purrr)
cluster_by_name <- function (y) {
map(unique(names(y)), ~ paste(unique(y[which(names(y)==.)]), collapse=", ")) %>%
setNames(unique(names(y)))
}
flatten_sublist <- function(x, colnames) {
for (colname in colnames){
x <- append(x, unlist(x[[colname]]))
x[[colname]] <- NULL
}
x
}
vec <- c("A"=1,"B"=2, "A"=1, "B"=4)
vec2 <- c("A2"=1,"B2"=2, "A2"=3, "B2"=4)
init_list <- list(vec=vec, C=1, vec2=vec2)
init_list # starting point
list_clustered_by_name <- init_list %>%
map_if(function(x) length(x) > 1,
function (y) cluster_by_name(y)
)
list_clustered_by_name # possible starting point
# $vec
# $vec$A
# [1] "1"
# $vec$B
# [1] "2, 4"
# $C
# [1] 1
# $vec2
# $vec2$A2
# [1] "1, 3"
# $vec2$B2
# [1] "2, 4"
composed <- keep(list_clustered_by_name, ~(length(.) > 1), ~.)
single_features <- keep(list_clustered_by_name, ~(length(.) == 1), ~.)
composed_flattened <- flatten_sublist(composed, names(composed))
desired_list <- c(composed_flattened, single_features)
desired_list
# $A
# [1] "1"
# $B
# [1] "2, 4"
# $A2
# [1] "1, 3"
# $B2
# [1] "2, 4"
# $C
# [1] 1
This might work for you:
library(purrr)
map_if(init_list, ~ length(.x) > 1, ~ as.list(tapply(.x, names(.x), \(y) toString(unique(y))))) |>
list_flatten(name_spec = "{inner}")
$A
[1] "1"
$B
[1] "2, 4"
$C
[1] 1
$A2
[1] "1, 3"
$B2
[1] "2, 4"