【问题标题】:Partial matching a list to a list of lists将列表部分匹配到列表列表
【发布时间】:2016-01-05 15:42:16
【问题描述】:

我对 R 还是很陌生,我很难正确地措辞这个问题,所以如果这是重复的,我提前道歉。

我有一个固定长度列表的列表,所有列表都具有相同的命名成员。这是我的haystack。
我有一个包含命名成员的列表,但有些丢失了。这是我的needle。

如果needle 存在于haystack 中,我想返回一个简单的TRUE/FALSE。

示例:

这应该返回 TRUE:needle 的所有成员都匹配 haystack[[1]],即使它缺少 c

haystack <- list( list(a = 1, b = 2, c = 3), list(a = 4, b = 5, c = 6) )
needle <- list(a = 1, b = 2)
something(needle, haystack)

这应该返回 FALSE:needle 的值与 haystack[[1]] 匹配,但它们的名称不同

haystack <- list( list(a = 1, b = 2, c = 3), list(a = 4, b = 5, c = 6) )
needle <- list(x = 1, y = 2)
something(needle, haystack)

这应该返回 FALSE:a = 1 和 b = 5 存在于 haystack 中,但不在同一个列表中

haystack <- list( list(a = 1, b = 2, c = 3), list(a = 4, b = 5, c = 6) )
needle <- list(a = 1, b = 5)
something(needle, haystack)

到目前为止,我发现的最接近的是 lapply(haystack, match, table = needle),但 A) 它不尊重名称匹配和 B) 我不确定如何将其结果转换为逻辑结果。

如果有一个库可以让这更容易,请随时将其合并到您的答案中。

【问题讨论】:

  • “我有一个固定长度的列表,所有的成员都具有相同的名称。” -- 使用 data.frame:x = do.call(rbind.data.frame, haystack) 或类似的。
  • @Frank - 在我的工作结束时,我做 将结果转换为数据框。我仍在学习 R 语言,而且我更熟悉操作列表而不是操作数据框。 :(

标签: r list


【解决方案1】:

这可能有点粗糙,但我认为它可以完成这项工作。我们需要在这里解决的问题是匹配名称和值。一个非常简单的方法是将它们粘贴在一起。

haystack2 <- lapply(haystack,function(x){
  res <- paste0(names(x),x)
  res
})
# > haystack2
# [[1]]
# [1] "a1" "b2" "c3"
# 
# [[2]]
# [1] "a4" "b5" "c6"

needle2 <- paste0(names(needle),needle)
# > needle2
# [1] "a1" "b2"

然后我们可以使用 lapply 和 %in%:

res <- any(sapply(haystack2,function(x) all(needle2 %in% x)))
# > res
# [1] TRUE

包装在一个函数中很容易,可以选择返回找到针头的大海捞针的索引。

something <- function(haystack, needle, position=F){
  haystack2 <- lapply(haystack,function(x) paste0(names(x),x))
  needle2 <- paste0(names(needle),needle)
  res <- sapply(haystack2,function(x) all(needle2 %in% x))
  if(position){
    return(which(res))
  } 
  return(any(res))
}

【讨论】:

    【解决方案2】:

    受@Heroka 回答的启发:

    any(
        sapply(
            haystack,
            function(h) all( unlist( needle ) == unlist( h[names(needle)] ) )
        )
    )
    

    这个想法是h[names(needle)] 按照名称在needle 中出现的顺序返回来自h 的值列表。我们将其转换为向量,丢弃名称但保留顺序。如果向量的all 元素匹配needle 转换为向量,则此条目表示匹配。

    如果haystack 中的列表中的any 返回true,我们将返回TRUE 作为最终结果。

    【讨论】:

    • 非常聪明!由于您消除了名称,因此无需粘贴。
    【解决方案3】:

    好吧,在我编写函数时,这里有很好的答案,比我的要好得多。所以,为了做出一点小小的贡献,这就是我想出的。

    myFunc <- function(haystack, needle, n = length(needle)){
      values <- sapply(haystack, match, table = needle)
      names <- sapply(lapply(haystack,names), match, table = names(needle))
      for(i in 1:ncol((mtx = values * names))) {
        if(sum(!is.na(mtx[,i]))==n) return(TRUE)
      }
      return(FALSE)
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-31
      相关资源
      最近更新 更多