R语言 通过索引获取字符串的最后一部分

ffdz8vbo  于 2023-02-17  发布在  其他
关注(0)|答案(3)|浏览(324)

我必须用分隔符“-"分割一个字符串,并去掉最右边的部分。

  1. SKU <- c("PPM-UA-L", "RVK-JI-XL", "KMN-WO-XS", "YYL-S")

然而,在下面的代码中,[,3]并不适用于所有情况,因为其中一些代码只有一个“-"。在下面的示例中,最后一个值“YYL-S”将不返回任何内容。

  1. size <- str_split(SKU, "-", simplify = T)[ ,3]

我也试过用这个来做后向索引,但是得到了错误信息。也试过[,-1],但是R中的负索引号不表示后向计数。

  1. size <- str_split(SKU, "-", simplify = T)(rev[ ,3])
t1qtbnec

t1qtbnec1#

矢量化字符串操作比在内存中创建和销毁对象更快(参见下面的基准测试)

创建不需要的向量列表的解决方案往往相对较慢,您可以在这里使用正则表达式替换所有内容,包括最后的-

  1. sub(pattern = "^.+-", replacement = "", SKU)
  2. # [1] "L" "XL" "XS" "S"

插入符号(^)是匹配字符串开头的正则表达式metacharacter。匹配除新行之外的任何字符。+表示“匹配前面的字符一次或多次”。.+组合是greedy,表示它将查找从字符串开头到结尾的最长匹配。总而言之,这意味着,从字符串的开头开始匹配,直到并包括最后的-
sub()函数将x中第一个出现的pattern(在本例中为SKU)替换为replacement(在本例中为空字符串)。
您可以在这里阅读更多关于正则表达式中使用的语法。

基准测试

我以五种方法为基准:
1.底座R sub()
1.碱基R strsplit() |> sapply()
1.基础R strsplit() |> vapply()

  1. stringr::str_split_i() .
  2. stringr::str_split() |> vapply(\(x) tail(x, 1), character(1)) .
    1.基本R后视:regmatches(gregexpr() .
  3. stringr::str_extract()后视。
    我将向量从10重复到1e5多次。sub()始终是最快的方法,具有最少的垃圾收集(gc),即最少的内存分配。
    base::strsplit()stringr::str_split()之间没有太大的区别。sapply看起来与vapply()没有区别。stringr::str_split_i()比其他分割向量的方法更快,并且具有更少的垃圾收集,但不如sub()快。
    带lookbehind的stringr::str_extract()几乎和sub()一样快,而在带regmatches(gregexpr())的base R中使用相同的模式要慢得多(可能是因为它返回一个列表)。

生成绘图的代码

  1. results <- bench::press(
  2. rep_num = rep_nums,
  3. {
  4. x <- rep(SKU, rep_num)
  5. bench::mark(
  6. min_iterations = 10,
  7. sub = {
  8. sub("^.+-", "", x)
  9. },
  10. strsplit_base_sapply = {
  11. strsplit(x, "-") |>
  12. sapply(tail, 1)
  13. },
  14. strsplit_base_vapply = {
  15. strsplit(x, "-") |>
  16. vapply(\(x) tail(x, 1), character(1))
  17. },
  18. str_split_i = {
  19. str_split_i(x, "-", -1)
  20. },
  21. str_split_vapply = {
  22. str_split(x, "-") |>
  23. vapply(\(x) tail(x, 1), character(1))
  24. },
  25. base_r_lookbehind = {
  26. regmatches(
  27. x,
  28. gregexpr("(?<=-)[^-]+$", x, perl = TRUE)
  29. ) |> unlist()
  30. },
  31. stringr_lookbehind = {
  32. str_extract(x, "(?<=-)[^-]+$")
  33. }
  34. )
  35. }
  36. )
  37. library(ggplot2)
  38. autoplot(results) +
  39. theme_bw() +
  40. facet_wrap(vars(rep_num), scales = "free_x")
展开查看全部
gmol1639

gmol16392#

您可以将str_split_ii = -1一起使用来获取最后一部分:

  1. library(stringr) #1.5.0
  2. str_split_i(SKU, "-", -1)
  3. # [1] "L" "XL" "XS" "S"
xvw2m8pv

xvw2m8pv3#

为什么不将str_extract与lookbehind (?<=-)一起使用呢?lookbehind (?<=-)是一个否定字符类,不允许使用-字符,最后是最后一个位置锚$

  1. library(stringr)
  2. str_extract(SKU, "(?<=-)[^-]+$")
  3. [1] "L" "XL" "XS" "S"

相关问题