我写了R
函数insert
,以便在向量e
的给定位置p
插入给定元素v
。
这是:
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
函数编写等效函数吗?任何建议,帮助或更优雅高效的解决方案?提前谢谢。
答案 0 :(得分:4)
似乎存在许多问题,例如,插入顺序如何受先前插入的影响,以及插入多个元素的序列时该怎么做。这里我们有一个原始序列
x <- letters[1:10]
以及我们想要插入的一些内容
v <- LETTERS[1:4]
我们想要插入它们
at <- c(4, 7, 2, 6)
进行插入的一种方法是确定新索引值at
相对于原始值的顺序; order
正在提供稳定订单
o <- order(c(seq_along(x), at))
然后进行插入
> c(x, v)[o]
[1] "a" "b" "C" "c" "d" "A" "e" "f" "D" "g" "B" "h" "i" "j"
插入规则与原始
不完全相同> o = order(c(seq_along(a), z))
> c(a, z)[o]
a b c d e g f h j i
1 2 3 4 5 7 6 8 10 9
答案 1 :(得分:2)
这是一种允许after
的多个值的方法(要求值为相同长度的列表
vappend <- function(x, values, after){
lx <- length(x)
if(missing(after)){
after <- length(x)
}
la <- length(after)
if(la ==1L){
return(append(x, unlist(values), after))
} else {
stopifnot(length(values) == length(after))
lv <- sapply(values, length)
aae <- rep.int(after,lv)
c(x, unlist(values))[order(c(seq_along(x), aae))]
}
}
vappend(x = 1:5, values = list(2:3,3:5),after = 1:2)
## [1] 1 2 3 2 3 4 5 3 4 5
答案 2 :(得分:1)
对我来说,看起来你只是追加价值而不是指数决定的“位置”。在这种情况下,您只需使用c
和order
。
a <- c(1, 2, 3, 4, 5, 7, 8, 10)
names(a) <- letters[a]
a
## a b c d e g h j
## 1 2 3 4 5 7 8 10
z <- c(6, 9)
names(z) <- letters[z]
z
## f i
## 6 9
result <- c(a, z)[order(c(a, z))]
result
## a b c d e f g h i j
## 1 2 3 4 5 6 7 8 9 10