结合列表元素?

时间:2012-06-14 10:04:09

标签: r list element

我有两个长列表A和B,它们具有相同的长度,但包含不同数量的等效元素:
列表A可以包含许多元素,这些元素也可以在同一个字段中重复出现 列表B或者只包含一个元素或一个空字段,即“字符(0)” A还包含一些空字段但是对于这些记录,B中总是存在一个元素,因此A和B中没有空字段的记录。
我想根据以下规则将A和B的元素组合成一个长度相同的新列表C:

  • A中的所有元素必须存在于C中 - 包括它们在同一领域中的潜在复发。
  • 如果B包含一个元素,该元素在同一记录的A中不存在,它也将被添加到C中。
  • 但是如果B包含已存在于同一记录的A中的元素,则它将被忽略。
  • 如果A有一个空字段,则此记录的B元素将添加到C.
  • 如果B有一个空字段,则该记录中A的元素将被添加到C.

这是这些列表开始的示例:

> A  
 [1] "JAMES" "JAMES"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID" "WILLIAM"  
 [4] character(0)  
...  
> B  
 [1] "RICHARD"  
 [2] "JOHN"  
 [3] character(0)  
 [4] "CHARLES"  
...  

这是我正在寻找的正确输出:

> C  
 [1] "JAMES" "JAMES" "RICHARD"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID" "WILLIAM"  
 [4] "CHARLES"  
... 

我试过了,例如:

C <- sapply(mapply(union, A,B), setdiff, character(0))  

但不幸的是,这删除了A的复发:

> C  
 [1] "JAMES" "RICHARD"  
 [2] "JOHN" "ROBERT"  
 [3] "WILLIAM" "MICHAEL" "DAVID"  
 [4] "CHARLES"  
...  

请有人告诉我,如何将这两个列表结合起来,保留A的重复,并实现我想要的输出?

非常感谢你!

更新:机读数据:

A <- list(c("JAMES","JAMES"),
          c("JOHN","ROBERT"), 
          c("WILLIAM","MICHAEL","WILLIAM","DAVID","WILLIAM"),  
          character(0))
B <- list("RICHARD","JOHN",character(0),"CHARLES")

1 个答案:

答案 0 :(得分:7)

以下是您可以重现的数据:

A <- list(c("JAMES","JAMES"),
          c("JOHN","ROBERT"), 
          c("WILLIAM","MICHAEL","WILLIAM","DAVID","WILLIAM"),  
          character(0))
B <- list("RICHARD","JOHN",character(0),"CHARLES")

你与mapply()关系密切。我使用c()来连接AB中的列表元素,但必须操纵所提供向量的元素,从而得到了所需的输出,所以我提出了这个:

foo <- function(...) {
    l1 <- length(..1)
    l2 <- length(..2)
    out <- character(0)
    if(l1 > 0) {
        if(l2 > 0) {
            out <- if(..2 %in% ..1)
                ..1
            else
                c(..1, ..2)
        } else {
            out <-  ..1
        }
    } else {
        out <-  ..2
    }
    out
}

我们可以使用...占位符来引用..n的各个元素; ..1A..2B。当然,foo()仅适用于两个列表,但不强制执行此操作或执行任何检查,只是为了简单起见。 foo()还需要处理AB或两者都是character(0)的情况,我现在认为foo()会这样做。

当我在mapply()电话中使用时,我得到:

> mapply(foo, A, B)
[[1]]
[1] "JAMES"   "JAMES"   "RICHARD"

[[2]]
[1] "JOHN"   "ROBERT"

[[3]]
[1] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID"   "WILLIAM"

[[4]]
[1] "CHARLES"

lapply()版本可能比抽象..n更有意义,但使用的代码基本相同。这是一个直接与AB配合使用的新功能,但我们会迭代由A生成的1, 2, 3, length(A)seq_along())元素的索引:

foo2 <- function(ind, A, B) {
    l1 <- length(A[[ind]])
    l2 <- length(B[[ind]])
    out <- character(0)
    if(l1 > 0) {
        if(l2 > 0) {
            out <- if(B[[ind]] %in% A[[ind]]) {
                A[[ind]]
            } else {
                c(A[[ind]], B[[ind]])
            }
        } else {
            out <- A[[ind]]
        }
    } else {
        out <- B[[ind]]
    }
    out
}

这样称呼:

> lapply(seq_along(A), foo2, A = A, B = B)
[[1]]
[1] "JAMES"   "JAMES"   "RICHARD"

[[2]]
[1] "JOHN"   "ROBERT"

[[3]]
[1] "WILLIAM" "MICHAEL" "WILLIAM" "DAVID"   "WILLIAM"

[[4]]
[1] "CHARLES"