假设我有List
个元素(< 20),但每个元素都是几个元素的矢量(IntegerVector
,Numericvector
或CharacterVector
) GB。因此我想避免任何副本。
要从我的List
中删除元素,我会编写以下Rcpp代码:
void list_remove_element (List x, int i) {
Rcout << "Size before : " << x.size() << endl;
x.erase(i);
Rcout << "Size after : " <<x.size() << endl;
}
Internaly,这段代码有效地擦除了相应的。遗憾的是,在返回此功能后,R中没有出现任何变化:
> u = list(a=1:5, b=3:4, c=5:6)
> list_remove_elements (u, 1)
Size before : 3
Size after : 2
> str(u)
List of 3
$ a: int [1:5] 1 2 3 4 5
$ b: int [1:2] 3 4
$ c: int [1:2] 5 6
据我所知,使用函数增大或缩小Rcpp对象会导致数据从原始对象复制到新对象中。有没有解决方法可以避免这种情况?
编辑:
我也尝试过以下操作:
void list_remove_elements (SEXP x) {
SET_VECTOR_ELT(x, 1, R_NilValue);
}
自从我得到它后几乎可以工作:
> str(u)
List of 3
$ a: int [1:5] 1 2 3 4 5
$ b: NULL
$ c: int [1:2] 5 6
但我仍然有元素'b',并且不确定这是正确的方法......
答案 0 :(得分:2)
使用现有列表中的某些元素创建新列表不会复制内容,即
> data <- list( x = rnorm(1e6), y = rnorm(1e6), z = rnorm(1e6) ).
> pryr::object_size(data)
24 MB
> data2 <- data[ c("x", "y") ]
> pryr::object_size(data2)
16 MB
但data
和data2
分享他们的记忆
> pryr::object_size(data, data2)
24 MB
只有当你的make更改为data2 $ x
时,才会复制内存> data2$x[1] <- 12
> pryr::object_size( data, data2 )
32 MB
在原始list_remove_element
功能中,您只需返回x
这将是一个新列表:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List list_remove_element (List x, int i) {
x.erase(i);
return x ;
}
/*** R
data <- list( x = rnorm(1e6), y = rnorm(1e6), z = rnorm(1e6) )
data2 <- list_remove_element(data, 1)
pryr::object_size(data)
pryr::object_size(data2)
pryr::object_size(data, data2)
*/
给出:
> Rcpp::sourceCpp('~/Desktop/test.cpp')
> data <- list( x = rnorm(1e6), y = rnorm(1e6), z = rnorm(1e6) )
> data2 <- list_remove_element(data, 1)
> pryr::object_size(data)
24 MB
> pryr::object_size(data2)
16 MB
> pryr::object_size(data, data2)
24 MB
答案 1 :(得分:0)
如果您将参数重命名为&#39; List&amp; x&#39;,那么你应该得到理想的结果。
如下所示:
void list_remove_element (List& x, int i) {
Rcout << "Size before : " << x.size() << endl;
x.erase(i);
Rcout << "Size after : " <<x.size() << endl;
}