list 在 R 中合并两个列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9519543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:47:43  来源:igfitidea点击:

Merge Two Lists in R

rlistdataframe

提问by Michael

I have two lists

我有两个清单

first = list(a = 1, b = 2, c = 3)
second = list(a = 2, b = 3, c = 4)

I want to merge these two lists so the final product is

我想合并这两个列表,所以最终产品是

$a
[1] 1 2

$b
[1] 2 3

$c
[1] 3 4

Is there a simple function to do this?

有没有一个简单的功能来做到这一点?

回答by Andrei

If lists always have the same structure, as in the example, then a simpler solution is

如果列表始终具有相同的结构,如示例中所示,那么更简单的解决方案是

mapply(c, first, second, SIMPLIFY=FALSE)

回答by IRTFM

This is a very simple adaptation of the modifyList function by Sarkar. Because it is recursive, it will handle more complex situations than mapplywould, and it will handle mismatched name situations by ignoring the items in 'second' that are not in 'first'.

这是 Sarkar 对 modifyList 函数的一个非常简单的改编。因为它是递归的,所以它将处理比mapply原来更复杂的情况,并且它将通过忽略不在 'first' 中的 'second' 中的项目来处理不匹配的名称情况。

appendList <- function (x, val) 
{
    stopifnot(is.list(x), is.list(val))
    xnames <- names(x)
    for (v in names(val)) {
        x[[v]] <- if (v %in% xnames && is.list(x[[v]]) && is.list(val[[v]])) 
            appendList(x[[v]], val[[v]])
        else c(x[[v]], val[[v]])
    }
    x
}

> appendList(first,second)
$a
[1] 1 2

$b
[1] 2 3

$c
[1] 3 4

回答by Aaron left Stack Overflow

Here are two options, the first:

这里有两个选项,第一个:

both <- list(first, second)
n <- unique(unlist(lapply(both, names)))
names(n) <- n
lapply(n, function(ni) unlist(lapply(both, `[[`, ni)))

and the second, which works only if they have the same structure:

第二个,只有当它们具有相同的结构时才有效:

apply(cbind(first, second),1,function(x) unname(unlist(x)))

Both give the desired result.

两者都给出了想要的结果。

回答by Max Gordon

Here's some code that I ended up writing, based upon @Andrei's answer but without the elegancy/simplicity. The advantage is that it allows a more complex recursive merge and also differs between elements that should be connected with rbindand those that are just connected with c:

这是我最终根据@Andrei 的回答编写的一些代码,但没有优雅/简单。优点是它允许更复杂的递归合并,并且在应该连接的元素rbind和刚刚连接的元素之间也有所不同c

# Decided to move this outside the mapply, not sure this is 
# that important for speed but I imagine redefining the function
# might be somewhat time-consuming
mergeLists_internal <- function(o_element, n_element){
  if (is.list(n_element)){
    # Fill in non-existant element with NA elements
    if (length(n_element) != length(o_element)){
      n_unique <- names(n_element)[! names(n_element) %in% names(o_element)]
      if (length(n_unique) > 0){
        for (n in n_unique){
          if (is.matrix(n_element[[n]])){
            o_element[[n]] <- matrix(NA, 
                                     nrow=nrow(n_element[[n]]), 
                                     ncol=ncol(n_element[[n]]))
          }else{
            o_element[[n]] <- rep(NA, 
                                  times=length(n_element[[n]]))
          }
        }
      }

      o_unique <- names(o_element)[! names(o_element) %in% names(n_element)]
      if (length(o_unique) > 0){
        for (n in o_unique){
          if (is.matrix(n_element[[n]])){
            n_element[[n]] <- matrix(NA, 
                                     nrow=nrow(o_element[[n]]), 
                                     ncol=ncol(o_element[[n]]))
          }else{
            n_element[[n]] <- rep(NA, 
                                  times=length(o_element[[n]]))
          }
        }
      }
    }  

    # Now merge the two lists
    return(mergeLists(o_element, 
                      n_element))

  }
  if(length(n_element)>1){
    new_cols <- ifelse(is.matrix(n_element), ncol(n_element), length(n_element))
    old_cols <- ifelse(is.matrix(o_element), ncol(o_element), length(o_element))
    if (new_cols != old_cols)
      stop("Your length doesn't match on the elements,",
           " new element (", new_cols , ") !=",
           " old element (", old_cols , ")")
  }

  return(rbind(o_element, 
               n_element, 
               deparse.level=0))
  return(c(o_element, 
           n_element))
}
mergeLists <- function(old, new){
  if (is.null(old))
    return (new)

  m <- mapply(mergeLists_internal, old, new, SIMPLIFY=FALSE)
  return(m)
}

Here's my example:

这是我的例子:

v1 <- list("a"=c(1,2), b="test 1", sublist=list(one=20:21, two=21:22))
v2 <- list("a"=c(3,4), b="test 2", sublist=list(one=10:11, two=11:12, three=1:2))
mergeLists(v1, v2)

This results in:

这导致:

$a
     [,1] [,2]
[1,]    1    2
[2,]    3    4

$b
[1] "test 1" "test 2"

$sublist
$sublist$one
     [,1] [,2]
[1,]   20   21
[2,]   10   11

$sublist$two
     [,1] [,2]
[1,]   21   22
[2,]   11   12

$sublist$three
     [,1] [,2]
[1,]   NA   NA
[2,]    1    2

Yeah, I know - perhaps not the most logical merge but I have a complex parallel loop that I had to generate a more customized .combinefunction for, and therefore I wrote this monster :-)

是的,我知道 - 也许不是最合乎逻辑的合并,但我有一个复杂的并行循环,我必须为其生成一个更自定义的.combine函数,因此我写了这个怪物:-)

回答by csta

In general one could,

一般来说,可以,

merge_list <- function(...) by(v<-unlist(c(...)),names(v),base::c)

Note that the by()solution returns an attributed list, so it will print differently, but will still be a list. But you can get rid of the attributes with attr(x,"_attribute.name_")<-NULL. You can probably also use aggregate().

请注意,该by()解决方案返回一个attributed 列表,因此它将以不同的方式打印,但仍将是一个列表。但是您可以使用attr(x,"_attribute.name_")<-NULL. 您可能也可以使用aggregate().