将序列拆分为子序列(可能使用正则表达式)

时间:2015-01-17 23:26:18

标签: regex r sequence

我有一个字符序列的序列,大多数是零,一个非常小的块看起来像这样:

  

0001001099991091010000100005480010000

我想获得由一个或多个零分隔的所有碎片。所以在上面的例子中,返回的正确值是:

  

1,1,99991,91,1,1,548,1(逗号仅供参考)

我认为向量列表最适合作为返回的数据结构,但我可以使用任何合理的方法。我有成千上万的字符串,每个字符串最多只有一千个字符。但是唯一的字符是0到9。这似乎可能是一个正则表达式问题,但我的正则表达式技能还不够好,甚至不能确定它是一个很好的正则表达式问题。如果一个正则表达式是答案,有人可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:5)

如果字符串与显示的字符串类似,那么strplit()可以为您执行此操作:

vec <- "0001001099991091010000100005480010000"
strsplit(vec, "[0]+")

给出

> strsplit(vec, "[0]+")
[[1]]
[1] ""      "1"     "1"     "99991" "91"    "1"     "1"     "548"   "1"

这是一个包含一个组件的列表(我们传递了一个字符串进行拆分),但如果在向量中传递n个字符串,则返回的对象将具有n个组件。每个组件都包含您想要的子字符串。

如果您希望将这些作为数字,则需要转换为数字,但这很简单。另一个问题是在示例字符串的开头运行000。这导致空字符串"",它是拆分字符串的第一个元素。我们也需要删除它们。

out <- strsplit(vec, "[0]+")
out <- lapply(out, function(x) as.numeric(x[nzchar(x)]))

这给出了

> out
[[1]]
[1]     1     1 99991    91     1     1   548     1

关于使用的正则表达式的注释:[0]+。括号括起我们想要匹配的内容,在这种情况下只包含0 s。 +表示“一个或多个”。这就是为什么这有效,因为strplit()会在有一个或多个0 s的地方切断提供的字符串。

答案 1 :(得分:3)

对于数千个字符串,您可能希望使用非常高效的stringi包。

x <- "0001001099991091010000100005480010000"

library(stringi)
stri_sub(x, stri_locate_all_regex(x, "[^0]+")[[1L]])
# [1] "1"     "1"     "99991" "91"    "1"     "1"     "548"   "1" 

基本上,这是在x中找到所有非零字符块并返回子字符串。要在多个字符串上应用此方法,您可以使用Map()

y <- rep(x, 3)
Map(stri_sub, y, stri_locate_all_regex(y, "[^0]+"))
# $`0001001099991091010000100005480010000`
# [1] "1"     "1"     "99991" "91"    "1"     "1"     "548"   "1"    
#
# $`0001001099991091010000100005480010000`
# [1] "1"     "1"     "99991" "91"    "1"     "1"     "548"   "1"    
#
# $`0001001099991091010000100005480010000`
# [1] "1"     "1"     "99991" "91"    "1"     "1"     "548"   "1"    

包中还有一个stri_split()函数,但它会在开头留下空字符(如strsplit()),并且它们的结尾为零。

答案 2 :(得分:0)

@ gavin的答案是更优雅的答案,但蛮力方法也有效:

input = '0001001099991091010000100005480010000'
output = character(0)
while(nchar(input)){
    if(grepl('^0',input)){
        # get rid of the unwanted bits
        input = gsub('^0+','',input)
        next
    }
    # keep the good bits
    output = c(output,gsub('0.*','',input))
    input = gsub('^[1-9]*','',input)
}