我有一个字符序列的序列,大多数是零,一个非常小的块看起来像这样:
0001001099991091010000100005480010000
我想获得由一个或多个零分隔的所有碎片。所以在上面的例子中,返回的正确值是:
1,1,99991,91,1,1,548,1(逗号仅供参考)
我认为向量列表最适合作为返回的数据结构,但我可以使用任何合理的方法。我有成千上万的字符串,每个字符串最多只有一千个字符。但是唯一的字符是0到9。这似乎可能是一个正则表达式问题,但我的正则表达式技能还不够好,甚至不能确定它是一个很好的正则表达式问题。如果一个正则表达式是答案,有人可以帮我解决这个问题吗?
答案 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)
}