删除列表组件中已经出现在R中早期组件中的元素

qyyhg6bp  于 2023-06-19  发布在  其他
关注(0)|答案(4)|浏览(81)

我有一个列表,每个组件都是一个数字向量。组件中有一些通用的数字。下面是一个例子:

ls <- list(c(7, 4, 9), c(5, 9, 2, 19), c(3, 13, 4, 2))

组件% 2的第二个元素已经出现在组件% 1中。组件3的第3和第4个元素已经分别出现在组件1和2中。我想删除后面的组件中已经出现在前面的组件中的元素。对于具体的示例,我想要ls2 <- list(c(7, 4, 9), c(5, 2, 19), c(3, 13))
我想写一个R脚本,自动执行上面的任务,它可以推广到其他列表。

fnvucqvd

fnvucqvd1#

使用setdiff

ls <- list(c(7, 4, 9), c(5, 9, 2, 19), c(3, 13, 4, 2))

foo <- function(x) {
  for (i in seq_along(x)[-1]) {
    x[[i]] <- setdiff(ls[[i]], unlist(ls[seq_len(i - 1)]))
  }
  x
}

ls2 <- foo(ls)
#[[1]]
#[1] 7 4 9
#
#[[2]]
#[1]  5  2 19
#
#[[3]]
#[1]  3 13
b91juud3

b91juud32#

对每个元素使用setdiff(),删除所有以前看到的元素。首先,我们需要列出以前看到的元素:

ls <- list(c(7, 4, 9), c(5, 9, 2, 19), c(3, 13, 4, 2))

accumulated <- Reduce(union, ls, accumulate = TRUE)
accumulated
#> [[1]]
#> [1] 7 4 9
#> 
#> [[2]]
#> [1]  7  4  9  5  2 19
#> 
#> [[3]]
#> [1]  7  4  9  5  2 19  3 13

然后,对于列表中的每个元素,我们将其与先前看到的元素的累积列表进行比较。注意,我们需要分隔列表的第一个元素:

c(ls[1],
  lapply(seq_along(ls)[-1],
         \(i) setdiff(ls[[i]], accumulated[[i - 1]])))
#> [[1]]
#> [1] 7 4 9
#> 
#> [[2]]
#> [1]  5  2 19
#> 
#> [[3]]
#> [1]  3 13
nkkqxpd9

nkkqxpd93#

您可以unlist并检查duplicated值,然后relist并使用索引删除重复项:

dup <- relist(duplicated(unlist(ls)), skeleton = ls)
mapply(function(x, y) x[!y], ls, dup)

# [[1]]
# [1] 7 4 9
# 
# [[2]]
# [1]  5  2 19
# 
# [[3]]
# [1]  3 13
bvk5enib

bvk5enib4#

我们可以尝试stack + subset + unstack

unstack(
    subset(
        stack(setNames(lst, seq_along(lst))),
        !duplicated(values)
    )
)

它给出了

$`1`
[1] 7 4 9

$`2`
[1]  5  2 19

$`3`
[1]  3 13

相关问题