【问题标题】:gsub return an empty string when no match is found找不到匹配项时 gsub 返回一个空字符串
【发布时间】:2012-04-18 17:23:07
【问题描述】:

我在 R 中使用 gsub 函数在文本列表中返回我的模式(参考编号)的出现。除非找不到匹配项,否则这很好用,在这种情况下,我会取回整个字符串,而不是空字符串。考虑这个例子:

data <- list("a sentence with citation (Ref. 12)",
             "another sentence without reference")

sapply(data, function(x) gsub(".*(Ref. (\\d+)).*", "\\1", x))

返回:

[1] "Ref. 12"                            "another sentence without reference"

但我想得到

[1] "Ref. 12"                            ""

谢谢!

【问题讨论】:

  • gsub 不能(当前为 2.15.0)这样做,因为:“如果 replacement 包含未在 pattern 中定义的反向引用,则结果未定义(但通常采用反向引用成为"")。”

标签: r regex gsub


【解决方案1】:

我可能会走另一条路,因为sapply 对我来说似乎没有必要,因为这些函数已经矢量化了:

fun <- function(x){
    ind <- grep(".*(Ref. (\\d+)).*",x,value = FALSE)
    x <- gsub(".*(Ref. (\\d+)).*", "\\1", x)
    x[-ind] <- ""
    x
}

fun(data)

【讨论】:

  • 有什么理由使用grep而不是grepl
  • @David 我不这么认为,这只是我的手指碰巧首先输入的内容。
【解决方案2】:

根据文档,这是gsub 的一个功能,如果没有与提供的模式匹配,则返回输入字符串,匹配返回整个字符串。

在这里,我首先使用函数grepl 来返回给定字符串中模式存在/不存在的逻辑向量:

ifelse(grepl(".*(Ref. (\\d+)).*", data), 
      gsub(".*(Ref. (\\d+)).*", "\\1", data), 
      "")

将其嵌入函数中:

mygsub <- function(x){
     ans <- ifelse(grepl(".*(Ref. (\\d+)).*", x), 
              gsub(".*(Ref. (\\d+)).*", "\\1", x), 
              "")
     return(ans)
}

mygsub(data)

【讨论】:

    【解决方案3】:
    xs <- sapply(data, function(x) gsub(".*(Ref. (\\d+)).*", "\\1", x))
    xs[xs==data] <- ""
    xs
    #[1] "Ref. 12" ""       
    

    【讨论】:

      【解决方案4】:

      试试 gsubfn 包中的strapplyc

      library(gsubfn)
      
      L <- fn$sapply(unlist(data), ~ strapplyc(x, "Ref. \\d+"))
      unlist(fn$sapply(L, ~ ifelse(length(x), x, "")))
      

      这给出了这个:

      a sentence with citation (Ref. 12) another sentence without reference 
                               "Ref. 12"                                 "" 
      

      如果您不介意列表输出,那么您可以使用 L 并忘记最后一行代码。请注意,fn$ 前缀会将其应用于函数的公式参数转换为函数调用,因此第一行代码可以在没有 fn 的情况下编写为 sapply(unlist(data), function(x) strapplyc(x, "Ref x. \\d+"))

      【讨论】:

      • 我从未见过 fn$ 被使用过 - 你在哪里找到的?
      • 在 gsubfn 包中,请参阅 ?fngsubfn 小插图的第 7 节。
      【解决方案5】:

      您可以尝试在该函数中嵌入grep( ..., value = T)

      data <- list("a sentence with citation (Ref. 12)",
               "another sentence without reference")
      
      unlist( sapply(data, function(x) { 
        x <- gsub(".*(Ref. (\\d+)).*", "\\1", x)
        grep( "Ref\\.", x, value = T )
        } ) )
      

      有点笨重,但它有效吗?它还会删除空的第二个引用。

      【讨论】:

      • 为我工作。就我而言,我将删除 unlist,因为我仍然想知道丢失的数据在哪里。谢谢!
      • @cboettig 请注意,sapply 在这里是多余的。
      • @joran 谢谢,我正在从一个我认为需要 sapply 的案例中简化示例,因为 data 是一个列表列表,忘记了我在这里不需要它。 ;-) 这样更好。
      【解决方案6】:

      基于@joran 的回答

      功能:

      extract_matches <- function(x,pattern,replacement,replacement_nomatch=""){
          x <- gsub(pattern,replacement,x)
          x[-grep(pattern,x,value = FALSE)] <- replacement_nomatch
          x
      }
      

      用法:

      data <- list("with citation (Ref. 12)", "without reference", "")
      extract_matches(data,  ".*(Ref. (\\d+)).*", "\\1")
      

      【讨论】:

        【解决方案7】:

        另一种简单的方法是使用 gsub,但在新函数中指定你想要的 ''

        noFalsePositives <- function(a,b,x) {
          return(ifelse(gsub(a,b,x)==x,'',gsub(a,b,x)))
        }
        # usage
        noFalsePositives(".*(Ref. (\\d+)).*", "\\1", data)
        # [1] "Ref. 12" "" 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 2015-05-20
          • 1970-01-01
          • 2019-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多