首页 > 解决方案 > 如何在使用 R 保留结构的同时从嵌套列表创建所有组合?

问题描述

给定一个嵌套列表,如何从其元素创建所有可能的列表,同时保留嵌套列表的结构?

嵌套列表:

l = list(
    a = list(
        b = 1:2
    ),
    c = list(
        d = list(
            e = 3:4,
            f = 5:6
        )
    ),
    g = 7
)

期望的输出: 的元素的所有可能组合l,同时保留结构,例如:

# One possible output:
list(
    a = list(
        b = 1
    ),
    c = list(
        d = list(
            e = 3,
            f = 5
        )
    ),
    g = 7
)

# Another possible output:
list(
    a = list(
        b = 1
    ),
    c = list(
        d = list(
            e = 4,
            f = 5
        )
    ),
    g = 7
)

到目前为止,我的方法是:

  1. 展平列表(例如,如本答案中所述)
  2. expand.grid()并得到一个矩阵,其中每一行代表一个唯一的组合
  3. 解析结果矩阵的每一行并names()使用正则表达式重构结构

我正在寻找一种不那么繁琐的方法,因为我不能保证列表元素的名称不会改变。

标签: rlistrecursion

解决方案


from的relist功能utils似乎是为此任务设计的:

rl <- as.relistable(l)
r <- expand.grid(data.frame(rl), KEEP.OUT.ATTRS = F)
> head(r, 5)
   b c.d.e c.d.f g
1  1     3     5 7
2  2     3     5 7
3  1     4     5 7
4  2     4     5 7
5  1     3     6 7

它保存了列表 ( skeleton) 的结构。这意味着现在可以操作嵌套列表中的数据并将其重新分配到结构 ( flesh) 中。这里是扩展矩阵的第一行。

r <- rep(unname(unlist(r[1,])),each = 2)
l2 <- relist(r, skeleton = rl)
> l2
$a
$a$b
[1] 1 1


$c
$c$d
$c$d$e
[1] 3 3

$c$d$f
[1] 5 5



$g
[1] 7

attr(,"class")
[1] "relistable" "list"  

请注意,由于结构保持不变,我需要提供与原始列表中相同数量的元素。这就是为什么rep要重复元素两次的原因。NA我猜也可以用 来填充它。

对于每个可能的组合迭代r(扩展):

lapply(1:nrow(r), function(x) 
          relist(rep(unname(unlist(r[x,])),each = 2), skeleton = rl))

推荐阅读