R-覆盖和递归合并列表

R-覆盖和递归合并列表,r,list,recursion,R,List,Recursion,假设我有两张有名字的名单 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 有什么提示吗

假设我有两张有名字的名单

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

有什么提示吗?

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

包含两个列表的函数,
list1
list2
。 如果:

  • 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)
}

我不确定这里是否需要自定义函数。有一个函数
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'

我不确定是否可以在保持嵌套结构的同时使用
vapply
/类似工具对其进行矢量化。太好了!正是我需要的。顺便说一句,我的示例中有一个“怪异”列表条目(
d
),如果添加
If(!is.null(a)&&&&!is.null(b)&&xor(is.list(a),is.list(b)){merged[[x]]我不知道为什么这不被认为是正确的answer@rmg我想,
modifyList
在2012年12月是相当新的,因此鲜为人知……而且我已经6年没有研究过这个问题了。@Zeemonkez感谢您的回答-我已经用了很多次了
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)
}
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