使用索引值将列表折叠为唯一组合

问题描述 投票:0回答:1

首先,我希望我能想出更好的方法来描述我的问题。我正在尝试使用以下示例列表:

lst<- list(c(2), c(1,3), c(2), c(4), c(6), c(5, 7), c(6,8), c(7))

然后把它变成这样:

res<- list(c(1,2,3), c(1,2,3), c(1,2,3), c(4), c(5,6,7,8), c(5,6,7,8),c(5,6,7,8), c(5,6,7,8))

甚至这个:

also_good_answer<- list(c(1, 2, 3), logical(0), logical(0), 4, c(5, 6, 7, 8), logical(0), 
    logical(0), logical(0))

我一直在使用几个

while
语句与
setdiff
组合来执行此操作,但我想知道是否有一种雄辩且更快的方法可以在一个大列表上执行此操作?

一如既往,预先感谢您。 -内特

我的方法:

lst<- list(c(2), c(1,3), c(2), c(4), c(6), c(5, 7), c(6,8), c(7)) # Original List
to_sequence<- 1:length(lst) 
res<- lapply(1:length(lst), function(x) {return(NA)})  # Building Result Object

while(length(to_sequence) > 0){
  tres<- c()
  idx<- to_sequence[1]
  next_idxs<- setdiff(lst[[idx]], NA)
  tres<- c(tres, next_idxs)
  while(length(next_idxs) >=1){
    next_idxs<- lapply(seq_along(next_idxs), function(x){
      lst[[next_idxs[x]]]
    } ) %>% unlist() %>% setdiff(., unlist(tres)) # uses slow setdiff
    tres<-c(tres, next_idxs)
  }
  res[[idx]]<- tres
  to_sequence<- setdiff(to_sequence, tres) # Another slow setdiff
  cat("Length to_sequence:", base::prettyNum(length(to_sequence),big.mark = ","), "\n") 
}

res<- lapply(res, sort)
r list reduce combine
1个回答
0
投票

我不完全确定我理解问题中的处理,但以下代码不使用

setdiff
(尽管它确实使用
intersect
并且没有显式循环为示例提供相同的结果。
ok
是 TRUE对于每个元素,其之前和之后的元素(之后包括元素本身)是不相交的。
cumsum(ok)
给出一个逻辑分组向量,然后我们创建一个列表
L
,其中包含每个组,最后重复所需的内容次数。

n <- length(lst)
ok <- sapply(seq_along(lst), function(i) {
  (i == 1) || length(intersect(unlist(lst[1:(i-1)]), unlist(lst[i:n]))) == 0
})
L <- tapply(lst, cumsum(ok), function(x) sort(unique(unlist(x))))
result <- rep(L, lengths(L))

str(result)

给予

List of 8
 $ 1: num [1:3] 1 2 3
 $ 1: num [1:3] 1 2 3
 $ 1: num [1:3] 1 2 3
 $ 2: num 4
 $ 3: num [1:4] 5 6 7 8
 $ 3: num [1:4] 5 6 7 8
 $ 3: num [1:4] 5 6 7 8
 $ 3: num [1:4] 5 6 7 8
© www.soinside.com 2019 - 2024. All rights reserved.