Я хочу преобразовать именованный список пар (key,values)
в именованный список пар (value,key)
. Можно с уверенностью предположить, что значения уникальны для ключей, но векторы имеют разную длину.
Я придумал решение, в котором используется purrr::map
, а затем purrr::flatten
.
Есть ли более элегантное решение?
library("tidyverse")
key_values_list <- list(
a = c("x", "y"),
b = c("A", "B", "C")
)
myinvert <- function(key, values) {
setNames(rep_along(values, key), values)
}
value_key_pairs <-
names(key_values_list) %>%
map(
~ myinvert(., key_values_list[[.]])
) %>%
flatten()
value_key_pairs
#> $x
#> [1] "a"
#>
#> $y
#> [1] "a"
#>
#> $A
#> [1] "b"
#>
#> $B
#> [1] "b"
#>
#> $C
#> [1] "b"
Created on 2022-03-16 by the reprex package (v2.0.1)
Мы можем использовать stack
с split
в base R
with(stack(key_values_list), split(as.character(ind), values))
Если нужно поддерживать порядок
with(stack(key_values_list), split(as.character(ind),
factor(values, levels = unique(values))))
Или с rep/lengths/unlist
setNames(as.list(rep(names(key_values_list),
lengths(key_values_list))), unlist(key_values_list))
@dipetkov stack/split
предполагает, что у вас нет пересекающихся значений в разных ключах.
В вашем случае это делает то, что вы хотите:
> library(hash)
> as.list(invert(hash(key_values_list)))
$x
[1] "a"
$y
[1] "a"
$A
[1] "b"
$B
[1] "b"
$C
[1] "b"
Спасибо! Я не знал о пакете hash
. Вот почему я определил функцию invert
в своем примере. Сейчас исправлено, чтобы не конфликтовало с hash::invert
.
Прохладно. Я не знал о
stack
иunstack
. У меня было подозрение, что "инвертировать" - не тот термин для поиска....