2

我有以下代码,我希望给我一个 3 的列表,因为有 3 个元素texts

library(stringr)
texts <- c("I doubt it! :)", ";) disagree, but ok.", "No emoticons here!!!")
smileys <- c(":)","(:",";)",":D")
str_extract_all(texts, fixed(smileys))

相反,我得到了四个列表(我的“模式”参数的长度,这里是smileys。此外,我收到以下警告消息:

警告消息:在 stri_extract_all_fixed(字符串,模式,简化 = 简化,:较长的对象长度不是较短对象长度的倍数```

好吧,我不认为长度匹配,因为我正在寻找每个文本中任何笑脸的任何点击。这不像我想将字符串 1 与模式 1 匹配,将字符串 2 与模式 2 匹配,等等。

意识到我弄乱了 stringi 对矢量化的理解,我尝试了这个:

texts %>% map(~ str_extract_all(.x, fixed(smileys)))

这要好得多,因为它给了我一个 3 的列表,但每个元素又是一个 4 的列表。

我想要的是一个尽可能少嵌套的 3 个列表。某个地方的某个人已经解决了这个问题,但我终其一生都无法弄清楚或无法通过谷歌搜索它。我可以为此做一个 for 循环,但我认为自己是 tidyverse 的公民......

感谢任何帮助。

4

1 回答 1

2

您可以使用将with和折叠的paste每个元素包装在正则表达式“或”元字符 ( ) 上以形成单个模式。正如Henrik在手册中分享和记录的链接中提到的那样,和之间的字符按字面意思解释。 smiley\\Q\\E|?regexstringi\\Q\\E

pattern <- paste("\\Q", smileys, "\\E", sep = "", collapse = "|")
# [1] "\\Q:)\\E|\\Q(:\\E|\\Q;)\\E|\\Q:D\\E"

library(stringi)
stri_extract_all_regex(texts, pattern)
#[[1]]
#[1] ":)"
#
#[[2]]
#[1] ";)"
#
#[[3]]
#[1] NA

基数 R:

regmatches(texts, gregexpr(pattern, texts))
#[[1]]
#[1] ":)"
#
#[[2]]
#[1] ";)"
#
#[[3]]
#character(0)  
       # If you want an NA, instead of a zero-length vector, 
       # then you could do something like:
       # lapply(
       #   regmatches(texts, gregexpr(pattern, texts)), 
       #   function(ii) ifelse(is.character(ii) & length(ii) == 0L, NA, ii))

如果您确实想使用purrr和避免使用正则表达式,一个想法是这样的:

library(purrr)
library(stringr)
texts %>% 
  map(~ unlist(str_extract_all(.x, fixed(smileys))))
#[[1]]
#[1] ":)"
#
#[[2]]
#[1] ";)"
#
#[[3]]
#character(0)  
       # if you want NA, not a zero-length vector, you could add:
       # %>% map(~ ifelse(is.character(.x) & length(.x) == 0L, NA, .x))
于 2017-01-24T22:36:41.987 回答