在 *apply 中退出一个函数

Exit a function within *apply

sapplyreplicate(等)运行 指定的次数。放sapply(1:N, function(n){expr})会执行exprN次。假设我希望 sapply 在 m 运行 秒后停止。这有可能不出错吗? break 不起作用,forwhile 循环在我的上下文中太慢了。

类似于:

sapply(1:N, function(n){
  #some expression
  if(identical(n, m)) break
})

除了 break 不起作用。

我想做什么:

创建一个函数来读取已定义结构但长度未知的大型(二进制)数据文件。使用 replicatearray(readBin(...), ...) 是我发现的最好的方法,但我希望它在 NA 开始返回时停止(即到达文件末尾) .

除了 for*apply 的战斗之外,如果您的问题是使用 readBin 直到到达文件末尾,请记住:

  • 您可以(小)高估 n(要读取的元素数);
  • 通过file.info(filename)$size可以知道文件的大小;那么你可以自己估算一下文件中包含了多少个元素。

例如,假设您正在读取整数(四个字节)值。试试看:

readBin(con,"int",n=file.info(filename)$size/4+10)

一次读取所有文件。 +10是高估了一点

可以以全局控制变量的形式使用部分解决方法

i<-TRUE
unlist( sapply(1:10, function(x){if(i){ if(x>=4)(i<<-FALSE); 2*x;}}) ) 

虽然还是跑了n次,但至少不是每次都执行操作,节省资源。 而且我无法完全弄清楚为什么简化一直没有奏效,我不得不使用 unlist。

以为我会 post 我为此想到了什么。 cbb 是正在构建的数组。在坏的例子中,cbb 使用 abind 逐渐构建为数组。在每一步,cbb 都必须重新评估,因此每个连续的步骤都比较慢 - 一个不断增长的对象。在这个好例子中,cbb 被构建为一个列表,并且每一步都会声明一个新的列表条目。 R 不需要每次都重新评估现有列表。该数组在末尾用 do.call(abind, c(cbb, list(along = 4))).

绑定在一起

我觉得有帮助的一件事是将 cat(".") 放在循环中。如果点打印速度减慢,则可能表示物体正在生长。在这个好例子中,点的打印速度或多或少是恒定的。好的例子比坏的例子快十倍。

差:

cbb <- array(NA, c(N1, N2, N3, 0))
repeat{ 
    sptsnew <- readBin(to.read, "integer", 2L, 4L)
    if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
    ... #reading array metadata
    cbb <- abind(cbb, array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1)), along = 4)
    cat(".")
}

好:

i <- 1
cbb <- list()
repeat{ 
    sptsnew <- readBin(to.read, "integer", 2L, 4L)
    if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
    ... #reading array metadata
    cbb[[i]] <- array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1))
    i <- i + 1
    cat(".")
}
cbb <- do.call(abind, c(cbb, list(along = 4)))