从字符串的开头和结尾删除数字

7

我有以下向量:

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

我想要移除"5lang"中的"5""kasverschil2"中的"2"。但是我不想移除"b2b"中的"2"


2
请注意,在下面的漂亮答案中,您可以将 \\d 替换为(在我看来)更易读的 [[:digit:]](特别是对于刚开始使用正则表达式或尝试阅读他人编写的代码的人)。 - hrbrmstr
@hrbrmstr 我同意这更易读。但这会降低速度吗? - Tyler Rinker
编译正则表达式可能需要几毫秒,但这不是速度瓶颈 :-) 另外要注意的是,\\d[[:digit:]] 可匹配所有 Unicode 数字,而 [0-9] 只能匹配标准十进制数字,因此在操作多样化环境中,任何一个都比 [0-9] 更好。 - hrbrmstr
3个回答

18
 gsub("^\\d+|\\d+$", "", words)    
 #[1] "lang"        "kasverschil" "b2b"

另一个选择是使用stringi

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

使用提供者在此处提供的数据集的变体,以下是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 结果有些惊讶。 - akrun
我认为这是因为它是一个非常简单的正则表达式。通常,stringi非常快速,但并非总是如此。另外,虽然stringi很快,但我真正喜欢的另一个好处是一致运行/命名的函数。这不像是一个狗,因为这些都是微秒级别的。所以,如果我要将其包含在软件包函数中,我可能会选择gsub,但对于分析,我会使用stringi方法(当然这只是个人意见)。 - Tyler Rinker

2
您可以使用使用正则表达式的 gsub 函数:
gsub("^[0-9]|[0-9]$", "", words)
# [1] "lang"        "kasverschil" "b2b"

说明:

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


3
如果在开头/结尾有多于一位数字,可能需要使用 [0-9]+|[0-9]+$ - akrun
当然,感谢您添加这个澄清。我刚写完你就基本上给出了相同的答案 ;) 但是增加了 stringi 库的价值,这是我之前不知道的。+1 - thothal

1
获取数字出现在单词开头或结尾的实例,并匹配其他所有内容。由于可能存在多个匹配项,您需要合并结果。
gregexpr(pattern='(^[0-9]+|[0-9]+$)', text = words) -> mm
sapply(regmatches(words, mm, invert=TRUE), paste, collapse="") 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接