Merge Two Lists in R

后端 未结 6 1107
南旧
南旧 2020-11-28 22:52

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

6条回答
  •  悲&欢浪女
    2020-11-28 23:52

    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 rbind and those that are just connected with 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 .combine function for, and therefore I wrote this monster :-)

提交回复
热议问题