我有一个生成一系列数据向量的例程,一次一次迭代。我想找到一种方法来“增长”列表或包含这些向量的矩阵。我试图创建一个列表,
PROTECT( myList = allocVector( VECSXP, 1 ) )
但是有没有办法通过推送一个向量元素来扩展列表?
另外,我不介意使用矩阵,因为我生成的向量具有相同的长度。
答案 0 :(得分:7)
Rf_lengthgets
中的 Rinternals.h
;在builtin.c:lengthgets
中实施。返回的指针需要被PROTECTed,因此一个模式是
SEXP myList;
PROTECT_INDEX ipx;
PROTECT_WITH_INDEX(myList = allocVector( VECSXP, 1 ), &ipx);
REPROTECT(mylist = Rf_lengthgets(mylist, 100), ipx);
如果一个人根据一些未知的停止条件增加一个列表,那么这个方法可能就像在R中一样,预分配和填充后跟扩展;以下是伪代码:
const int BUF_SIZE = 100;
PROTECT_INDEX ipx;
SEXP myList;
int i, someCondition = 1;
PROTECT_WITH_INDEX(myList=allocVector(VECSXP, BUF_SIZE), &ipx);
for (i = 0; some_condition; ++i) {
if (Rf_length(myList) == i) {
const int len = Rf_length(myList) + BUF_SIZE;
REPROTECT(myList = Rf_lengthgets(mYlist, BUF_SIZE), &ipx);
}
PROTECT(result = some_calculation();
SET_VECTOR_ELT(myList, i, result);
UNPROTECT(1);
// set some_condition
}
Rf_lengthgets(myList, i); // no need to re-PROTECT; we're leaving C
UNPROTECT(1)
return myList;
这会执行myList
的深层复制,因此可能会变得昂贵,并且在某种程度上,如果目标是评估some_calculation,那么看起来它更容易,而且效率也不会太低,无法进行预分配和扩展R循环中的操作,调用some_calculation并在循环内进行赋值。
答案 1 :(得分:6)
这是恕我直言,C ++击败C牌的好例子。
在C ++中,您可以使用STL容器(例如vector),并使用push_back()
轻松地一次插入一个元素。您永远不会使用malloc
或free
(或new
和delete
),而且您永远不会使用指针。在C中没有办法做到这一点。
同样,你可以利用R和C ++之间的Rcpp接口,这使得你在C ++中增长的数据更容易获得。