【问题标题】:Remove numbers at the beginning and end of a string删除字符串开头和结尾的数字
【发布时间】:2014-10-14 11:07:00
【问题描述】:

我有以下向量:

words <- c("5lang","kasverschil2","b2b")

我想删除"5lang" 中的"5" 和"kasverschil2" 中的"2"。但我不想在"b2b" 中删除"2"。

【问题讨论】:

  • 请注意,在下面的漂亮答案中,您可以将\\d 替换为(IMO)更具可读性的[[:digit:]](尤其适用于刚开始使用正则表达式或试图阅读其他人编写的代码的人)。
  • @hrbrmstr 我同意它更具可读性。这会导致速度下降吗?
  • 在正则表达式编译时可能需要几毫秒,但仅此而已,所以我不会将速度称为显示停止器 :-) 旁注:\\d 和 [[:digit:]] 匹配所有 unicode 数字,其中[0-9] 只匹配标准十进制数字,因此如果在不同的环境中运行,两者都比 [0-9] 好得多。

标签: r regex vector numbers


【解决方案1】:
 gsub("^\\d+|\\d+$", "", words)    
 #[1] "lang"        "kasverschil" "b2b"

另一种选择是使用stringi

 library(stringi)
 stri_replace_all_regex(words, "^\\d+|\\d+$", "")
  #[1] "lang"        "kasverschil" "b2b"        

这里使用 OP 提供的数据集的变体是 3 个三个主要解决方案的基准(请注意,这些字符串非常短且人为;结果可能在更大的真实数据集上有所不同):

words <- rep(c("5lang","kasverschil2","b2b"), 100000)

library(stringi)
library(microbenchmark)

GSUB <- function() gsub("^\\d+|\\d+$", "", words)
STRINGI <- function() stri_replace_all_regex(words, "^\\d+|\\d+$", "")
GREGEXPR <- function() {
    gregexpr(pattern='(^[0-9]+|[0-9]+$)', text = words) -> mm
    sapply(regmatches(words, mm, invert=TRUE), paste, collapse="") 
}

microbenchmark( 
    GSUB(),
    STRINGI(),
    GREGEXPR(),
    times=100L
)

## Unit: milliseconds
##        expr       min        lq    median        uq       max neval
##      GSUB()  301.0988  349.9952  396.3647  431.6493  632.7568   100
##   STRINGI()  465.9099  513.1570  569.1972  629.4176  738.4414   100
##  GREGEXPR() 5073.1960 5706.8160 6194.1070 6742.1552 7647.8904   100

【讨论】:

  • @Tyler Rinker 感谢您的基准测试。我对stringi 这里的结果有点惊讶。
  • 我认为这是因为它是如此简单的正则表达式。通常,stringi 速度非常快,但并非总是如此。此外,虽然stringi 速度很快,但我真正享受的另一个好处是始终如一的操作/命名功能。这不像是一只狗,因为这些都是微秒。因此,如果我将它包含在一个包函数中,我可能会使用gsub,但为了分析,我会使用stringi 方法(当然这都是意见)。
【解决方案2】:

您可以使用使用正则表达式的gsub:

gsub("^[0-9]|[0-9]$", "", words)
# [1] "lang"        "kasverschil" "b2b"

解释:

模式^[0-9] 匹配字符串开头的任意数字,而模式[0-9]$ 匹配字符串末尾的任意数字。通过| 分隔这两个模式,您希望匹配第一个或第二个模式。然后,将匹配的模式替换为空字符串。

【讨论】:

  • @thothal 如果开头/结尾有多个数字,则需要[0-9]+|[0-9]+$
  • 当然,感谢您添加此说明。我刚刚看到,在我写作的时候,你给出了基本相同的答案;)但是我还不知道stringi 库的附加值。 +1
【解决方案3】:

获取数字出现在单词开头或结尾的实例并匹配其他所有内容。由于可能有多个匹配项,您需要折叠结果:

gregexpr(pattern='(^[0-9]+|[0-9]+$)', text = words) -> mm
sapply(regmatches(words, mm, invert=TRUE), paste, collapse="") 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多