为每个状态获取整数值的一种简单方法是将值转换为整数,然后将每列乘以正确的基数。
我的版本是makecheck2
;使用的版本paste
是makecheck2
. 我还修改了paste
要使用的版本,match
以便它可以同时检查多个值。两个版本现在都返回一个用于获取匹配的函数。
我的版本设置更快;0.065 秒与 1.552 秒。
N <- 5
I <- rep(10,N)
S <- as.matrix(expand.grid( lapply(1:N, function(i) { 0:I[i]}) ) )
system.time(f1 <- makecheck1(S))
# user system elapsed
# 1.547 0.000 1.552
system.time(f2 <- makecheck2(S))
# user system elapsed
# 0.063 0.000 0.065
在这里,我用 1 到 10000 个值进行测试以进行检查。对于较小的值,该paste
版本更快;对于大值,我的版本更快。
> set.seed(5)
> k <- lapply(0:4, function(idx) sample(1:nrow(S), 10^idx))
> s <- lapply(k, function(idx) S[idx,])
> t1 <- sapply(s, function(x) unname(system.time(for(i in 1:100) f1(x))[1]))
> t2 <- sapply(s, function(x) unname(system.time(for(i in 1:100) f2(x))[1]))
> data.frame(n=10^(0:4), time1=t1, time2=t2)
n time1 time2
1 1 0.761 1.512
2 10 0.772 1.523
3 100 0.857 1.552
4 1000 1.592 1.547
5 10000 9.651 1.848
两个版本的代码如下:
makecheck2 <- function(m) {
codes <- vector("list", length=ncol(m))
top <- vector("integer", length=ncol(m)+1)
top[1L] <- 1L
for(idx in 1:ncol(m)) {
codes[[idx]] <- unique(m[,idx])
top[idx+1L] <- top[idx]*length(codes[[idx]])
}
getcode <- function(x) {
out <- 0L
for(idx in 1:length(codes)) {
out <- out + top[idx]*match(x[,idx], codes[[idx]])
}
out
}
key <- getcode(m)
f <- function(x) {
if(!is.matrix(x)) {
x <- matrix(x, ncol=length(codes))
}
match(getcode(x), key)
}
rm(m) # perhaps there's a better way to remove these from the closure???
rm(idx)
f
}
makecheck1 <- function(m) {
n <- ncol(m)
statecodes <- apply(m,1,function(x) paste(x,collapse=" ") )
rm(m)
function(x) {
if(!is.matrix(x)) {
x <- matrix(x, ncol=n)
}
x <- apply(x, 1, paste, collapse=" ")
match(x, statecodes)
}
}