R中列表中的匹配元素

Matching elements within list in R

假设我有一个列表,定义如下:

test <- list(1:4,5,8,1,2:3,10)

我想以某种方式匹配列表中包含任何相似数字的元素。例如,我想匹配 test[[1]]test[[4]],因为它们都包含 1。同样,test[[1]]test[[5]] 也会匹配,因为它们都包含 2 和 3。

匹配后,我想为每个匹配构造一个唯一的id。例如,答案将是以下列表

ans <- list(1,2,3,1,1,4)

编辑: 这个答案背后的直觉是,如果列表 test 的元素共享一个公共匹配项,它们将获得相同的 ID。这意味着即使 test[[4]]test[[5]] 不匹配,但它们都匹配 test[[1]] 的事实意味着它们将被分配相同的 id。

这显然是一个玩具示例。在实践中,我想将此匹配应用于一个大列表(>100,000k 元素)。考虑到这一点,算法需要有一定的效率。

提前致谢!

这可能是一个低效的答案,因为它嵌套了 for 和两个 if。不过它确实有效,所以它可能是您或其他人的起点。

test <- list(1:4,5,8,1,2:3,10)
ids <- 1

for (i in 2:length(test)) {     # start at second because next loop is backwards
  for (j in (i-1):1) {          # will match against previous items
    if (any(test[[j]] %in% test[[i]])) { # checks if there's any match between list items
      ids <- c(ids, ids[j])     # repeat the matched id
      break                     # leaves the loop if a match is found
    }
  }
  if (length(ids) < i) {        # if didn't match before
    ids <- c(ids, max(ids) + 1) # creates a new id from the last
  }
}
ids
# [1] 1 2 3 1 1 4

我还建议 运行 在更大的测试样本或部分真实数据上进行此操作,因为示例非常小,我可能会漏掉一些东西。

这是使用 data.table 的一种方法:

require(data.table)
# generate a data.table from your data
id = rep(seq_along(test), sapply(test, length))
dt = data.table(id, val = unlist(test))
# solution
dt[, ans := id[1L], by=val][, ans := .GRP, by=ans][, ans[1L], by=id]$V1
# [1] 1 2 3 1 1 4