问题描述:
假设一个向量由若干0和1 构成,我们想找出其中连续出现1的游程(在一个0和1组成的序列中,一个由连续的0或1构成的串称为一个游程)。。例如,对于向量(1,0,0,1,1,1,0,1,1),从它第4索引处开始有长度为3的游程,而长度为2的游程分别始于第4,第5和第8索引的位置。
代码如下:
findruns <- function(x, k){
n <- length(x)
runs <- NULL
for(i in 1:(n-k+1)){
if(all( x[i:(i+k-1)] == 1 ))
runs <- c(runs, i)
}
return( runs )
}
测试如下:
> y <- c( 1, 0, 0, 1, 1, 1, 0, 1, 1 )
> findruns( y, 3 )
[1] 4
> findruns( y, 2 )
[1] 4 5 8
> findruns( y, 6 )
NULL
第五行,我们需要判断从x[i]开始的连续k个值,即x[i],x[i+1],…,x[i+k-1]的值,是否全部为1。表达式x[i:(i+k-1)]语句给出了上述子向量的值,然后使用all()函数检验它是否是一个游程。
尽管前面的代码中使用all()比较好,但建立向量runs的过程并不理想。向量的内存分配过程比较耗时,由于调用c(runs,i)时给新的向量分配了内存空间,每次执行时都会减慢代码的运行速度。
代码改进:
findruns1 <- function(x, k){
n <- length(x)
runs <- vector( length=n )
count <- 0
for(i in 1:(n-k+1)){
if(all( x[i:(i+k-1)] == 1 )){
count <- count + 1
runs[count] <- i
}
}
if(count > 0){
runs <- runs[1:count]
}
else{
runs <- NULL
}
return( runs )
}
在第3行,我们给一个长度为n的向量分配了内存空间。这意味着在执行循环的过程中,可以避免分配新的内存。第8行代码做的只是填充runs。在退出函数之前,我们在第12行重新定义runs,来删除该向量中没用的部分。这种方法更好,第一版代码可能会有很多次内存分配,而第二版代码将之减少为两次。