以前所有的解決方案的隱含檢查向量的每一個元素。作爲@Robert庫布裏克指出,這並不需要的事實矢量已經排序的優勢。
要利用向量的排序自然優勢,您可以使用二進制搜索(通過findInterval
)找到起點和終點指標不看的每一個元素:
n<-1e9
v<--3:(n+3)
system.time(a <- v [v>=1 & v <=n]) # 68 s
system.time(b <- v[do.call(seq,as.list(findInterval(c(1,n),v)))]) # 15s
identical(a,b) # TRUE
這是一個有點笨拙,並有some discussion在findInterval
二進制搜索可能不完全有效的,但一般的概念是存在的。
正如在評論中指出的那樣,上述僅在索引處於向量中時才起作用。這是我認爲會起作用的一個功能:
in.range <- function(x, lo = -Inf, hi = +Inf) {
lo.idx <- findInterval(lo, x, all.inside = TRUE)
hi.idx <- findInterval(hi, x)
lo.idx <- lo.idx + x[lo.idx] >= lo
x[seq(lo.idx, hi.idx)]
}
system.time(b <- in.range(v, 1, n) # 15s
對於已排序的向量肯定會更快,但如果最小/最大元素包含在原始向量中,就會如@ flodel所指出的那樣工作。 – 2013-04-25 19:15:46
如果您好奇,我嘗試了'head' /'tail'方法和另一種方法,並將基準添加到我原來的問題中。 – 2013-04-25 19:44:15
@ flodel我喜歡編輯。我的功能很難看。 「all.inside」參數是矢量化的嗎?你可以做'findInterval(c(lo,hi),x,all.inside = c(TRUE,FALSE))' – nograpes 2013-04-25 19:59:09