Используйте ввод функции purrr map для создания именованного списка в качестве вывода в R

Я использую функцию отображения пакета purrr в R, которая дает в качестве вывода список. Теперь я хотел бы, чтобы выход был именованным списком на основе ввода. Пример приведен ниже.

input <- c("a", "b", "c")
output <- purrr::map(input, function(x) {paste0("test-", x)})

Из этого я хотел бы получить доступ к элементам списка, используя:

output$a

или

output$b

Ответ 1

Нам просто нужно назвать list

names(output) <- input

а затем извлеките элементы на основе имени

output$a
#[1] "test-a"

Если это нужно сделать, используя tidyverse

library(tidyverse)
output <- map(input, ~paste0('test-', .)) %>% 
                                setNames(input)

Ответ 2

Принятое решение работает, но страдает от повторного аргумента (input), который может вызвать ошибки и прерывать поток при использовании трубопровода с %>%.

Альтернативным решением было бы использовать немного больше мощности оператора %>%

1:5 %>% { set_names(map(., ~ .x + 3), .) } %>% print # ... or something else

Это берет аргумент из трубы, но все еще испытывает недостаток в некоторой красоте. Альтернативой может быть небольшой вспомогательный метод, такой как

map_named = function(x, ...) map(x, ...) %>% set_names(x)

1:5 %>% map_named(~ .x + 1)

Это уже выглядит более красиво и элегантно. И будет моим предпочтительным решением.

Наконец, мы могли бы даже перезаписать purrr::map в случае, если аргумент является символом или целочисленным вектором, и создать именованный список в таком случае.

map = function(x, ...){
    if (is.integer(x) | is.character(x)) {
        purrr::map(x, ...) %>% set_names(x)
    }else {
        purrr::map(x, ...) 
    }
}

1 : 5 %>% map(~ .x + 1)

Тем не менее, оптимальным решением было бы, если бы purrr реализовал такое поведение из коробки.