在两个指定的子字符串之间提取子字符串

Anj*_*jaM 1 regex grep r substr string-matching

我有一个子串列表,具有以下模式:

my.list <- list("file1\\subfile1-D.ext", "file12\\subfile9-D.ext", "file2\\subfile113-D.ext")
Run Code Online (Sandbox Code Playgroud)

等等.我想将文件号和子文件号提取到包含文件/子文件号的数字数据框中.到目前为止,我一直在使用以下方法:

extract.file <- function(file.name){
  file.name <- sub("file", "", file.name)
  file.name <- sub("\\\\*subfile.*", "", file.name)
}

extract.subfile <- function(subfile.name){
  subfile.name <- sub("file.*subfile", "", subfile.name)
  subfile.name <- sub("-D.ext", "", subfile.name)
}

name.file <- lapply(my.list, extract.file)
name.file <- as.numeric(unlist(name.file))
name.subfile <- lapply(my.list, extract.subfile)
name.subfile <- as.numeric(unlist(name.subfile))

my.df <- data.frame(file=name.file, subfile=name.subfile)
Run Code Online (Sandbox Code Playgroud)

我还玩过第一次substring.locationstringr库中提取字符串位置(产生另一个包含开始和结束值的列表),然后循环遍历两个列表,但这又变得太复杂了.有没有更好的方法来实现目标?

The*_*ell 5

一些替代方案:
[编辑:strsplit可以获取一个数组并返回一个列表,与在rbind调用中嵌套应用相比,将时间缩短一半左右.

my.df <- do.call( rbind, strsplit( unlist(my.list), split="(\\\\|-D.ext)" ) )
my.df <- data.frame( my.df )
names( my.df ) <- c("file", "subfile")
Run Code Online (Sandbox Code Playgroud)

要么

my.df <- do.call( rbind, strsplit( unlist(my.list), split="[^[:alnum:]]" ) )[, 1:2]
my.df <- data.frame( my.df )
names( my.df ) <- c("file", "subfile")
Run Code Online (Sandbox Code Playgroud)

以这种方式做事的一件事是,如果所有输入都遵循原始my.list样本,那么您将留下相当无价值且冗余的数据.

也许更好的解决方案可能是;

# Not sure why strsplit() returns an empty string on the first non-digit match,
# but it does and we account for it by dropping the first returned column.
my.list <- unlist( my.list )
my.df <- do.call( rbind, strsplit( my.list, split="[^[:digit:]]+" ) )[,-1]
my.df <- data.frame( my.list, my.df )
names( my.df ) <- c( "orig", "file", "subfile" )
Run Code Online (Sandbox Code Playgroud)

我们已经节省了相当多的内存/存储而没有所有这些重复,我们获得了操作事物的能力,而不必担心文本/字符排序/表示.


检查?strsplit,?regex?grep匹配的东西.

data.frame设置非常简单... strsplit接受一个向量并返回一个列表,而do.call需要一个列表绑定在一起.

  • 是.你需要``unlist`缠绕`strsplit`.我必须在评论之前开始测试代码.;-) (2认同)