3

我编写了一个R函数来在向量的给定位置insert插入给定元素。epv

这里是:

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

因此,我正在考虑的有关这两个功能(insertvinsert)的问题是:

  1. 返回一个新的向量或修改向量并返回它?
  2. Rcpp用?写一个等价的函数
  3. 可以使用一阶函数编写等效R函数吗?

有什么建议、帮助或更优雅有效的解决方案吗?提前致谢。

4

3 回答 3

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 
于 2013-04-11T00:14:48.137 回答
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
于 2013-04-10T23:35:04.057 回答
1

对我来说,您似乎只是附加在由值而不是索引确定的“位置”处。在这种情况下,您只需要使用cand 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 
于 2013-04-11T02:29:51.037 回答