好的,所以我对此进行了一些思考。不幸的是,我没有什么简单的东西(就像你要求的那样),但我已经把它分成了几种不同的方式,并认为它会很好分享。当然,如果你想要简单的话,你可以将其中任何一个变成一个函数。
另外,为了它的价值,我这样做是为了自学如何使用列表中的匹配文本,这就是为什么它倾向于成为顶部的小人物(也许)。
数据:
list1 <- list(c("Group1", "Group2", "Group3"))
list2 <- list(c("GroupA", "GroupB", "GroupC"))
list3 <- list(rep(paste0("Group", 1:1e5), 2))
list4 <- list(rep(paste0("Group", LETTERS), ceiling(2e5 / 26)))
list.12 <- c(list1,list2)
list.34 <- c(list3,list4)
返回向量的选项
选项 1(您的选择):
idx <- unlist(lapply(list.12, function(x) grepl("Group1", x, fixed = T)))
unlist(list.12)[idx]
[1] "Group1"
选项 2:
idx.list <- lapply(list.12, grepl, pattern = "Group1", fixed = TRUE)
match.list <- Map(`[`, list.12, idx.list)
unlist(match.list)
[1] "Group1"
选项 3:
unlist(list.12)[(grep("Group1", unlist(list.12), fixed = TRUE))]
[1] "Group1"
选项 4:
unlist(list.12)[(stri_detect_fixed(unlist(list.12), "Group1"))]
[1] "Group1"
以及小名单的基准:
Unit: microseconds
expr min lq mean median uq max neval
opt_1 7.001 8.305 153.6345 8.7790 9.668 1454.531 10
opt_2 12.234 12.433 14.6120 13.0425 14.481 26.645 10
opt_3 3.744 3.861 5.7395 4.0010 5.509 18.314 10
opt_4 4.511 4.763 7.1403 5.1635 6.047 18.205 10
输出list.34 以上所有选项:
[1] "Group1" "Group10" "Group11" "Group12" "Group13" "Group14"
[7] "Group15" "Group16" "Group17" "Group18" "Group19" "Group100"
[13] "Group101" "Group102" "Group103" "Group104" "Group105" "Group106"
[19] "Group107" "Group108" "Group109" "Group110" "Group111" "Group112"
...........
[997] "Group1885" "Group1886" "Group1887" "Group1888"
[ reached getOption("max.print") -- omitted 21224 entries ]
和基准(它们的价值):
Unit: milliseconds
expr min lq mean median uq max neval
opt_1 20.28270 21.59880 24.63574 22.97677 25.07883 34.28110 10
opt_2 15.65542 17.01358 19.29739 17.47097 18.95579 28.15225 10
opt_3 21.87411 23.17457 25.59646 24.06683 25.01356 40.57871 10
opt_4 31.78084 34.60584 38.84164 38.00180 42.79115 50.28889 10
所以看起来选项 2 使用更大的数据进行了最佳缩放。但是输出说明了为什么在使用grep、grepl 或其他使用正则表达式的函数时必须小心。
返回向量的“更安全”选项
因此,我认为包含一些“更安全”的选项可能会有所帮助。而且,更安全的是,我的意思是它们只会匹配文本“Group1”。它们也不会匹配“Group11...”
安全选项 1:
unlist(list.12)[match(unlist(list.12), "Group1", nomatch = F)]
[1] "Group1"
安全选项 2:
unlist(list.12)[unlist(list.12) %in% "Group1"]
[1] "Group1"
安全选项 3:
idx.list <- lapply(list.12, grepl, pattern = "\\bGroup1\\b")
match.list <- Map(`[`, list.12, idx.list)
unlist(match.list)
[1] "Group1"
以及“更安全”或精确单词匹配选项的基准:
Unit: microseconds
expr min lq mean median uq max neval
safe_1 3.063 3.124 3.9562 3.7135 4.172 7.157 10
safe_2 2.897 3.089 5.8281 3.3700 4.436 26.729 10
safe_3 27.978 28.564 34.1458 28.9110 30.869 75.457 10
输出 list.34 用于输出向量的所有更安全的选项:
[1] "Group1" "Group1"
这个输出是预期的,因为"Group1" 中只有两个list.34
list.34 的基准,以获得更安全的选项。
Unit: milliseconds
expr min lq mean median uq max neval
safe_1 13.79823 14.45908 17.40700 15.07796 23.18696 23.95939 10
safe_2 15.61516 17.61696 21.76075 21.15972 25.17552 28.91110 10
safe_3 120.27222 125.82341 129.01684 129.11074 131.15969 141.02159 10
返回列表的选项
最后,我认为将匹配项保持为列表形式可能也很有用。所以,我用了几种方法,并且也对它们进行了基准测试。请注意,选项 1 和 4 返回相同的结果,选项 2 和 3 返回大约。同样的结果。
列出选项 1:
idx.list <- lapply(list.12, grepl, pattern = "\\bGroup1\\b", fixed = F)
match.list <- Map(`[`, list.12, idx.list)
match.list[lapply(match.list, length) > 0]
[[1]]
[1] "Group1"
只返回匹配的元素
列出选项 2:
Filter(function(x) "Group1" %in% x, list.12)
[[1]]
[1] "Group1" "Group2" "Group3"
返回包含匹配元素的向量
列出选项 3:
list.12[which(unlist(list.12) %in% "Group1")]
[[1]]
[1] "Group1" "Group2" "Group3"
还返回包含匹配元素的向量
列出选项 4:
list4_ind <- Map(`%in%`, list.12[which(unlist(list.12) %in% "Group1")], "Group1")
Map(`[`, list.12[which(unlist(list.12) %in% "Group1")], list4_ind)
[[1]]
[1] "Group1"
与选项 1 一样,它只返回匹配的元素
列表选项的基准:
Unit: microseconds
expr min lq mean median uq max neval
list_opt_1 37.837 38.943 48.4543 46.3615 48.831 85.498 10
list_opt_2 8.474 9.749 243.2209 11.2840 12.538 2330.869 10
list_opt_3 3.384 3.876 4.9735 4.2705 5.051 11.233 10
list_opt_4 22.056 22.209 27.1948 25.8670 29.827 36.355 10
输出列表的所有选项的 list.34 的输出:
选项 1 和 4:
[[1]]
[1] "Group1" "Group1"
选项 2 & 3(实际上,选项 2 不会向列表返回空的第二个元素,仅返回 list1):
[[1]]
[1] "Group1" "Group2" "Group3" "Group4" "Group5" "Group6"
[7] "Group7" "Group8" "Group9" "Group10" "Group11" "Group12"
[13] "Group13" "Group14" "Group15" "Group16" "Group17" "Group18"
..........
[985] "Group985" "Group986" "Group987" "Group988" "Group989" "Group990"
[991] "Group991" "Group992" "Group993" "Group994" "Group995" "Group996"
[997] "Group997" "Group998" "Group999" "Group1000"
[ reached getOption("max.print") -- omitted 199000 entries ]
[[2]]
NULL
再次返回包含匹配项的整个向量。
和基准:
Unit: milliseconds
expr min lq mean median uq max neval
list_opt_1 120.899425 121.931426 128.245115 130.018640 131.247377 136.823413 10
list_opt_2 1.365003 2.398965 3.554334 2.499366 2.560078 9.524567 10
list_opt_3 11.169013 11.987195 16.755645 15.267181 21.299495 24.538944 10
list_opt_4 27.388212 32.125164 40.104322 40.680335 47.248335 48.679709 10
总结:
如果您想在不使用正则表达式的情况下返回精确(安全)模式的向量,那么安全选项 1 的缩放效果似乎最好。
如果您想使用正则表达式返回一个向量,安全选项 3 的缩放比例最佳以获取更多数据。与常规选项 2 相同。
如果您想要一个仅返回匹配项的列表,请使用列表选项 4。
如果您想要使用正则表达式仅包含匹配项的列表,请使用列表选项 1。
如果要返回包含匹配in 列表的向量,列表选项2 中的Filter 非常快。