我正在R
寻找一个函数partial.sum()
,它接受一个数字向量并返回所有部分和的升序排序向量:
test=c(2,5,10)
partial.sum(test)
# 2 5 7 10 12 15 17
## 2 is the sum of element 2
## 5 is the sum of element 5
## 7 is the sum of elements 2 & 5
## 10 is the sum of element 10
## 12 is the sum of elements 2 & 10
## 15 is the sum of elements 5 & 10
## 17 is the sum of elements 2 & 5 & 10
答案 0 :(得分:6)
这是一个使用递归。 (不要声称它有效率)
partial.sum <- function(x) {
slave <- function(x) {
if (length(x)) {
y <- Recall(x[-1])
c(y + 0, y + x[1])
} else 0
}
sort(unique(slave(x)[-1]))
}
partial.sum(c(2,5,10))
# [1] 2 5 7 10 12 15 17
编辑:好吧,事实证明它比我想象的要快一点:
x <- 1:20
microbenchmark(flodel(x), dason(x), matthew(x), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# flodel(x) 86.31128 86.9966 94.12023 125.1013 163.5824 10
# dason(x) 2407.27062 2461.2022 2633.73003 2846.2639 3031.7250 10
# matthew(x) 3084.59227 3191.7810 3304.36064 3693.8595 3883.2767 10
(我已将sort
和/或unique
添加到dason和matthew的职能部门,以便进行公平比较。)
答案 1 :(得分:3)
这可能不会很好地扩展,并且不会考虑输入向量中的可能重复或答案中的重复。如果您担心这一点,可以稍后使用unique
。
partial.sum <- function(x){
n <- length(x)
# Something that will help get us every possible subset
# of the original vector
out <- do.call(expand.grid, replicate(n, c(T,F), simplify = F))
# Don't include the case where we don't grab any elements
out <- head(out, -1)
# ans <- apply(out, 1, function(row){sum(x[row])})
# As flodel points out the following will be faster than
# the previous line
ans <- data.matrix(out) %*% x
# If you want only unique value then add a call to unique here
ans <- sort(unname(ans))
ans
}
答案 2 :(得分:2)
这是一种使用combn
生成求和组合的迭代方法。它适用于长度大于1的矢量。
partial.sum <- function(x) {
sort(unique(unlist(sapply(seq_along(x), function(i) colSums(combn(x,i))))))
}
## [1] 2 5 7 10 12 15 17
要处理小于2的长度,请测试长度:
partial.sum <- function(x) {
if (length(x) > 1) {
sort(unique(unlist(sapply(seq_along(x), function(i) colSums(combn(x,i))))))
} else {
x
}
}
rbenchmark
中的一些时间,不完全同意弗洛尔德的结果。我修改了Dason的代码,删除了评论并添加了对unique
的调用。我的代码版本是第一个,没有if
。 flodel的代码在这里是一个明显的赢家。
> test <- 1:10
> benchmark(matthew(test), flodel(test), dason(test), replications=100)
test replications elapsed relative user.self sys.self user.child sys.child
3 dason(test) 100 0.180 12.857 0.175 0.004 0 0
2 flodel(test) 100 0.014 1.000 0.015 0.000 0 0
1 matthew(test) 100 0.244 17.429 0.242 0.001 0 0
> test <- 1:20
> benchmark(matthew(test), flodel(test), dason(test), replications=1)
test replications elapsed relative user.self sys.self user.child sys.child
3 dason(test) 1 5.231 98.698 5.158 0.058 0 0
2 flodel(test) 1 0.053 1.000 0.053 0.000 0 0
1 matthew(test) 1 2.184 41.208 2.180 0.000 0 0
> test <- 1:25
> benchmark(matthew(test), flodel(test), dason(test), replications=1)
test replications elapsed relative user.self sys.self user.child sys.child
3 dason(test) 1 288.957 163.345 264.068 23.859 0 0
2 flodel(test) 1 1.769 1.000 1.727 0.038 0 0
1 matthew(test) 1 75.712 42.799 74.745 0.847 0 0