10

假设我有两个名称列表,

a = list( a=1, b=2, c=list( d=1, e=2 ), d=list( a=1, b=2 ) )
b = list( a=2, c=list( e=1, f=2 ), d=3, e=2 )

我想递归地合并这些列表,如果第二个参数包含冲突的值,则覆盖条目。即预期的输出将是

$a
[1] 2

$b
[1] 2

$c
$c$d
[1] 1

$c$e
[1] 1

$c$f
[1] 2

$d
[1] 3

$e
[1] 2

有什么提示吗?

4

2 回答 2

12

我不太确定这里是否需要自定义功能。有一个功能utils::modifyList()可以执行完全相同的操作!有关详细信息,请参阅修改列表

a <- list( a=1, b=2, c=list( d=1, e=2 ), d=list( a=1, b=2 ) )
b <- list( a=2, c=list( e=1, f=2 ), d=3, e=2 )

modifyList(a, b) # updates(modifies) 'a' with 'b'

这给出了以下

$a
[1] 2

$b
[1] 2

$c
$c$d
[1] 1

$c$e
[1] 1

$c$f
[1] 2

$d
[1] 3

$e
[1] 2 
于 2016-06-16T10:22:41.003 回答
9

我认为您必须在这里编写自己的递归函数。

一个接受两个列表的函数,list1list2。如果:

  • list1[[name]]存在但不存在list2[[name]],使用list1[[name]]
  • list1[[name]]存在以及list2[[name]]两者都不是列表,使用list2[[name]];
  • list1[[name]]否则,使用和list2[[name]]作为新列表进行递归。

就像是:

myMerge <- function (list1, list2) {
    allNames <- unique(c(names(list1), names(list2)))
    merged <- list1 # we will copy over/replace values from list2 as necessary
    for (x in allNames) {
        # convenience
        a <- list1[[x]]
        b <- list2[[x]]
        if (is.null(a)) {
            # only exists in list2, copy over
            merged[[x]] <- b
        } else if (is.list(a) && is.list(b)) {
            # recurse
            merged[[x]] <- myMerge(a, b)
        } else if (!is.null(b)) {
            # replace the list1 value with the list2 value (if it exists)
            merged[[x]] <- b
        }
    }
    return(merged)
}

注意事项 - 如果您要合并的列表很奇怪,您可能会得到奇怪的输出。例如:

a <- list( a=list(a=1, b=2), b=3 )
b <- list( a=2 )

然后你的合并列表有a=2, b=3. 这是因为 from 的值b$a会覆盖 from 的值a$a,即使a$a是一个列表(您没有指定如果是这种情况会发生什么)。myMerge但是,修改以处理这些情况很简单。请记住 - 用于is.list测试它是否是一个列表,并查看列表中是否存在is.null(myList$a)条目。amyList


这是使用的“矢量化”版本sapply

merge.lists <- function(a, b) {
    a.names <- names(a)
    b.names <- names(b)
    m.names <- sort(unique(c(a.names, b.names)))
    sapply(m.names, function(i) {
        if (is.list(a[[i]]) & is.list(b[[i]])) merge.lists(a[[i]], b[[i]])
        else if (i %in% b.names) b[[i]]
        else a[[i]]
    }, simplify = FALSE)
}
于 2012-12-11T00:24:43.780 回答