【问题标题】:Extract substring between two specified substrings提取两个指定子串之间的子串
【发布时间】:2012-08-13 14:51:20
【问题描述】:

我有一个具有以下模式的子字符串列表:

my.list <- list("file1\\subfile1-D.ext", "file12\\subfile9-D.ext", "file2\\subfile113-D.ext")

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

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)

我还尝试过首先使用 substring.locationstringr 库中提取字符串位置(这会产生另一个具有开始和结束值的列表),然后循环这两个列表,但这又变得太复杂了.有没有更好的方法来实现目标?

【问题讨论】:

    标签: r regex string-matching substr


    【解决方案1】:

    一些替代方案:
    [编辑:strsplit 可以接受一个数组并返回一个列表,与在 rbind 调用中嵌套一个 apply 相比,时间减少了大约一半。]

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

    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")
    

    以这种方式做事的一件事是,如果所有输入都遵循原始 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" )
    

    我们已经节省了相当多的内存/存储空间而没有所有这些重复,并且我们获得了操作事物的能力,而无需担心文本/字符顺序/表示。


    检查 ?strsplit?regex?grep 以获取匹配的内容。

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

    【讨论】:

    • 我发现lapplydo.call(rbind, ...) 一起使用时比sapply 更安全。毕竟,rbind 正在为您简化工作。
    • @Gsee,因为strsplit 将返回一个列表,而lapply 将返回一个列表,然后需要unlistrecursive=FALSE 才能将正确级别的列表传递给@987654336 @,是吗?
    • 是的。您需要将unlist 包裹在strsplit 周围。我必须在评论之前开始测试代码。 ;-)
    • 感谢您提出这个问题!让我回去再次查看 strsplit 输出,这导致了答案的编辑。 :)
    • @Thell 这太完美了,正是我需要得到的输出,并且以一种非常好的和清晰的方式。非常感谢!
    【解决方案2】:

    这是一个带有反向引用的正则表达式,似乎可以满足您的要求:

    sapply(my.list, function(x)gsub(".*\\\\(.*)-D\\.ext", "\\1", x))
    [1] "subfile1"   "subfile9"   "subfile113"
    

    "\\1" 是一个反向引用,它返回括号内字符串的值。

    【讨论】:

    • 非常感谢,这很有帮助!
    猜你喜欢
    • 2017-05-12
    • 2020-09-22
    • 2022-09-28
    • 2023-01-11
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多