用R计算字符串中空格的序列

时间:2018-03-26 10:36:23

标签: r regex performance

我想检索字符串中连续空格的序列。喜欢:

mystring="lalalal  lalalal lalala   lalalala "
retrieve_sequence_of_consecutive_blanks(mystring)
[1] 2 1 3 1

实际上,我得到了一个解决方案,用这个

sequence_of_blanks=function(vectors_of_strings){
  tokens=strsplit(x = mystring,split = "",fixed = TRUE)
  sequence=lapply(X = tokens,FUN = rle)
  resultats=lapply(sequence, function(item){
    resultats=item$lengths[which(item$values==" ")]
  })
}

我的问题是关于表现,您认为是否有更好的方法可以做到这一点? 正则表达式解决方案怎么样? python解决方案怎么样?

3 个答案:

答案 0 :(得分:2)

您可以匹配所有空间块并获取它们的长度,例如

library(stringr)
nchar(unlist(str_extract_all(mystring, " +")))

或基本R等价物:

nchar(unlist(regmatches(mystring, gregexpr(" +", mystring))))

两者都屈服

[1] 2 1 3 1

在Python中,您可以使用

[x.count(" ") for x in re.findall(" +", mystring)]

请参阅Python demo

如果您计划计算任何空格,请将文字空间替换为\s。根据您的进一步要求进行调整。

答案 1 :(得分:2)

您可以使用

myrle <- rle(charToRaw(mystring) == charToRaw(" "))
myrle$lengths[myrle$values]

有点快:

microbenchmark::microbenchmark(
  OP = sequence_of_blanks(mystring),
  akrun = tabulate(cumsum(c(TRUE, diff(str_locate_all(mystring, " ")[[1]][,2]) !=1))),
  wiktor = nchar(unlist(str_extract_all(mystring, " +"))),
  # charToRaw(mystring) == charToRaw(" "),
  fprive = { myrle <- rle(charToRaw(mystring) == charToRaw(" ")); myrle$lengths[myrle$values] }
)

Unit: microseconds
   expr    min     lq     mean  median      uq     max neval
     OP 32.826 37.680 42.97734 42.3940 46.3405 115.239   100
  akrun 40.718 44.874 48.40903 48.4360 50.7050  78.991   100
 wiktor 24.166 29.753 34.73199 35.0955 36.7370 129.626   100
 fprive 23.258 25.877 29.50010 28.6000 31.6730  43.721   100

如果你真的需要性能,为你的特定用途设计一些Rcpp函数,作为参数charToRaw(mystring)charToRaw(" ")将提高性能。

答案 2 :(得分:0)

如果你想使用简单的基础R来获得更多的性能:

length_seq_blanks <- function(string) {
  x <- nchar(unlist(strsplit(string, "[a-z]+")))
  x[x > 0]
}

length_seq_blanks(mystring)
[1] 2 1 3 1

基准

microbenchmark::microbenchmark(
  snoram = {
    length_seq_blanks <- function(string) {
      x <- nchar(unlist(strsplit(string, "[a-z]+")))
       x[x > 0]
    }
    length_seq_blanks(mystring) 
  },
  fprive = {
    myrle <- rle(charToRaw(mystring) == charToRaw(" "))
    myrle$lengths[myrle$values]
  },
  unit = "relative"
)
Unit: relative
   expr      min       lq     mean   median       uq     max neval
 snoram 1.000000 1.000000 1.000000 1.000000 1.000000 1.00000   100
 fprive 1.866597 1.818247 1.734015 1.684211 1.634093 1.20812   100