在列表元素的子集上使用 lapply 和与 R 中原始长度相同的 return 列表

Use lapply on a subset of list elements and return list of same length as original in R

我想使用 lapply 和 return 与原始长度相同的列表,将正则表达式操作应用于列表元素的子集(字符串)。列表元素是长字符串(源自读取长文本文件并将段落折叠成单个字符串)。正则表达式操作仅对列表 elements/strings 的子集有效。我希望将非子集列表元素(字符串)return编辑为原始状态。

正则表达式操作是 str_extract 来自 stringr 包,即我想从一个较长的字符串中提取一个子字符串。我根据文件名中的正则表达式模式对列表元素进行子集化。

简化数据的示例:

library(stringr)
texts <- as.list(c("abcdefghijkl", "mnopqrstuvwxyz", "ghijklmnopqrs", "uvwxyzabcdef"))
filenames <- c("AB1997R.txt", "BG2000S.txt", "MN1999R.txt", "DC1997S.txt")
names(texts) <- filenames
regexp <- "abcdef"

我事先知道要对哪些字符串应用正则表达式操作,因此我想对这些字符串进行子集化。也就是说,我不想 运行 列表中所有元素的正则表达式,因为这样做会 return 一些无效结果(这在这个简化的示例中并不明显)。

我做了一些幼稚的努力,例如:

x <- lapply(texts[str_detect(names(texts), "1997")], str_extract, regexp)
> x
$AB1997R.txt
[1] "abcdef"

$DC1997S.txt
[1] "abcdef"

其中 return 是一个缩减长度的列表,仅包含找到的子字符串。 但是我想要得到的结果是:

> x
$AB1997R.txt
[1] "abcdef"

$BG2000S.txt
[1] "mnopqrstuvwxyz"

$MN1999R.txt
[1] "ghijklmnopqrs"

$DC1997S.txt
[1] "abcdef"

其中不包含正则表达式模式的字符串 return 以其原始状态编辑。

我已经了解了 stringrlapplyllply(在 plyr 包中),但是许多操作都是使用数据框作为示例进行说明的,而不是列表,并且不涉及对字符串的正则表达式操作。我可以使用 for 循环实现我的目标,但我正在尝试摆脱它,正如通常建议的那样,并更好地使用函数的 apply-class 。

您可以使用子集运算符 [<-:

x <- texts
is1997 <- str_detect(names(texts), "1997")
x[is1997] <- lapply(texts[is1997], str_extract, regexp)
x
# $AB1997R.txt
# [1] "abcdef"
#
# $BG2000S.txt
# [1] "mnopqrstuvwxyz"
#
# $MN1999R.txt
# [1] "ghijklmnopqrs"
#
# $DC1997S.txt
# [1] "abcdef"
#

你可以试试sub

  sub(paste0('.*(', regexp, ').*'), '\1', texts)
  # AB1997R.txt      BG2000S.txt      MN1999R.txt      DC1997S.txt 
  #  "abcdef" "mnopqrstuvwxyz"  "ghijklmnopqrs"         "abcdef" 

此外,如果您需要将 'texts' 的名称与 1997 匹配,我们可以使用 grep

  indx <- grep('1997', names(texts))
  texts[indx] <- sub(paste0('.*(', regexp, ').*'), '\1', texts[indx])
  as.list(texts)