2013-07-01 20 views
9

Jestem zaintrygowany.Jak uzyskać dostęp do elementów wektora w Rcpp :: List

Poniższy skompilować i działa prawidłowo:

#include <Rcpp.h> 
using namespace Rcpp; 
// [[Rcpp::export]] 
List test(){ 
    List l; 
    IntegerVector v(5, NA_INTEGER); 
    l.push_back(v); 
    return l; 
} 

w R:

R) test() 
[[1]] 
[1] NA NA NA NA NA 

Ale gdy próbuję ustawić IntegerVector w liście:

// [[Rcpp::export]] 
List test(){ 
    List l; 
    IntegerVector v(5, NA_INTEGER); 
    l.push_back(v); 
    l[0][1] = 1; 
    return l; 
} 

to nie kompilacja:

test.cpp:121:8: error: invalid use of incomplete type 'struct SEXPREC' 
C:/PROGRA~1/R/R-30~1.0/include/Rinternals.h:393:16: error: forward declaration of 'struct SEXPREC' 

Odpowiedz

15

To właśnie z powodu tej linii:

l[0][1] = 1; 

Kompilator nie ma pojęcia, że ​​l jest lista wektorów całkowitych. Zasadniczo l[0] daje ci SEXP (typ ogólny dla wszystkich obiektów R), a SEXP jest nieprzezroczystym wskaźnikiem do SEXPREC, którego nie mamy dostępu do definicji te (stąd nieprzejrzysty). Więc kiedy robisz [1], próbujesz zdobyć drugi SEXPREC, więc krycie sprawia, że ​​jest to niemożliwe, i nie jest to, co i tak chciałeś.

Musisz być specyficzne, że jesteś uzyskiwaniu IntegerVector, więc można zrobić coś takiego:

as<IntegerVector>(l[0])[1] = 1; 

lub

v[1] = 1 ; 

lub

IntegerVector x = l[0] ; x[1] = 1 ; 

Wszystkie te opcje działają na tej samej podstawowej strukturze danych.

Alternatywnie, jeśli naprawdę chciałeś składni l[0][1], możesz zdefiniować swoją własną strukturę danych wyrażającą "listę wektorów całkowitych". Oto szkic:

template <class T> 
class ListOf { 
public: 

    ListOf(List data_) : data(data_){} 

    T operator[](int i){ 
     return as<T>(data[i]) ; 
    } 
    operator List(){ return data ; } 

private: 
    List data ; 
} ; 

Których można użyć, np. tak:

// [[Rcpp::export]] 
List test2(){ 
    ListOf<IntegerVector> l = List::create(IntegerVector(5, NA_INTEGER)) ; 
    l[0][1] = 1 ; 
    return l; 
} 

Należy również pamiętać, że korzystanie .push_back na Rcpp wektory (w tym listy) wymaga kompletną kopię listy danych, które mogą powodować powolne dół. Używaj funkcji zmiany rozmiaru tylko wtedy, gdy nie masz wyboru.

+1

Parfait! bardzo dziękuję za odpowiedź ! – statquant

+0

Jeszcze jedno pytanie Romain, czy mogę utworzyć '' Rcpp :: List' zawierającą 'n' (powiedzmy 3)' std :: vector 'lub' Rcpp :: IntegerVector' z jedną linią (może być 'ctor'), np. 'IntegerVector v (3, NA_INTEGER); Rcpp :: List test (3, v) ' – statquant

+0

Przeznaczony jest do pracy:' Lista l (3, IntegerVector (3, NA_INTEGER)) ', ale w jednym z naszych plików występuje literówka (' fill__dispatch' jest napisane jako 'fill_dispatch' (jeden podkreślenie)), więc nie powiedzie się. Naprawiłem to lokalnie i wkrótce zatwierdzę poprawkę. –

Powiązane problemy