【发布时间】:2013-04-02 23:49:41
【问题描述】:
我写了一个R 函数insert 将给定元素e 插入向量v 的给定位置p。
这里是:
insert <- function(v, e, p) {
if (length(e) != 1 || length(p) != 1) {
stop('supported the insertion of only one element per call.')
}
len <- length(v)
nms <- names(v)
enm <- names(e)
res <- NULL
if (p > 1 && p <= len) {
res <- c(v[1:(p-1)], e, v[p:len]) # insert
} else if (p == 1) {
res <- c(e, v) # prepend
} else if (p == (len+1)) {
res <- c(v, e) # append
} else {
stop('wrong position')
}
if (!is.null(enm)) {
names(res) <- insert(nms, enm, p)
}
res
}
请注意,此函数与 R 中的几乎所有内容一样,返回一个新向量。此外(参见递归调用),它还插入元素的名称,如果它有的话。
这是一个简单的使用示例:
a <- c(1,2,3,4,5,7,8,10)
names(a) <- c(letters[1:5], letters[7:8], letters[10])
a
# a b c d e g h j
# 1 2 3 4 5 7 8 10
b <- c(9)
names(b) <- letters[9]
insert(a, b, 8)
# a b c d e g h i j
# 1 2 3 4 5 7 8 9 10
我正在尝试编写此函数的矢量化(高效)版本。
现在,我写了一个有点优雅的解决方案:
vinsert <- function(v, elems, positions) {
out <- v
for (i in 1:length(elems)) {
out <- insert(out, elems[i], positions[i])
}
out
}
这里是一个简单的使用示例:
a <- c(1,2,3,4,5,7,8,10)
names(a) <- c(letters[1:5], letters[7:8], letters[10])
a
# a b c d e g h j
# 1 2 3 4 5 7 8 10
z <- c(6,9)
names(z) <- c(letters[6], letters[9])
z
# f i
# 6 9
vinsert(a, z, z)
# a b c d e f g h i j
# 1 2 3 4 5 6 7 8 9 10
所以,我正在考虑的关于这两个函数(insert 和 vinsert)的问题是:
- 返回一个新的向量还是在原地修改向量并返回?
- 用
Rcpp写一个等价的函数? - 是否可以使用一阶
R函数编写等效函数?
有任何建议、帮助或更优雅高效的解决方案吗?提前致谢。
【问题讨论】:
-
有一个未矢量化的
base函数append似乎可以执行您希望insert执行的操作。 -
@mnel:你是对的,谢谢。
append相当于我的insert函数。仍然存在在不同位置插入更多元素的矢量化和有效解决方案的问题。 -
我认为除非向量被过度分配,否则您将无法就地修改,否则您将不会返回全长向量(或者我可能不理解您的意思1)
标签: r vector vectorization