Как добавить элементы из второго списка к существующим элементам из первого списка в R

#r #purrr

#r #purrr

Вопрос:

У меня есть два списка x и y:

 x <- list(id1 = list(a = list(t = 5)), id2 = list(a = list(t = 1), b = list(t = 3)), id3 = list(a = list(t = 1), b = list(t = 2)))

y <- list(b = list(k = 7))
  

Мне нужно изменить список x и добавить соответствующие элементы «b» из списка y, чтобы получить список z:

 z <- list(id1 = list(a = list(t = 5)), id2 = list(a = list(t = 1), b = list(t = 3, k = 7)),
  id3 = list(a = list(t = 1), b = list(t = 2, k = 7)))
  

Я пытаюсь использовать list_modify(x, y) и list_merge(x, !!!y) из purrr пакета, но получаю неверный результат.
Как это сделать в R?

Ответ №1:

В этом случае вы могли бы сделать:

 result <- lapply(x, function(i) {
  if("b" %in% names(i)) i$b <- append(i$b, y$b); i;
  })

  

Такой, что

 identical(result, z)
#> [1] TRUE
  

Ответ №2:

Это не особенно элегантно, но вы могли бы использовать цикл для этого. Цикл проходит по элементам внутри x и внутри, элементы внутри y . Если есть элемент in x с тем же именем, что и элемент in y , они объединяются вместе в z , в противном случае z это просто x . В зависимости от масштаба реальной проблемы это может быть слишком медленно, и, возможно, кто-то может предоставить аккуратную альтернативу.

 z <- vector(mode="list", length = length(x))  
for(i in 1:length(x)){
  for(j in 1:length(y)){
    z[[i]] <- x[[i]]
    if(names(y)[j] %in% names(x[[i]])){
      z[[i]][[names(y)[j]]] <- c(x[[i]][[names(y)[j]]], y[[j]])
    }else{
      
    }
    names(z) <- names(x)
  }
}
  

Ответ №3:

Альтернативное решение с использованием map_if : применить list_merge к каждому элементу в исходном списке, который имеет хотя бы одно общее с y :

 map_if(x, ~any(names(.) %in% names(y)), list_merge, !!!y)
  

Ответ №4:

purrr::list_merge работает, как и ожидалось, но когда спискам присваиваются имена, он использует имена для поиска позиций для слияния, и ваш y неправильно назван с помощью id2 / id3 для слияния.

Чтобы использовать list_merge:
y <- list(id2 = list(b = list(k = 7)), id3 = list(b = list(k = 7)))

z2 <- list_merge(x, !!!y)

identical(z, z2)

[1] ВЕРНО