2014-01-09 4 views
2

Новое в Rcpp Я тестирую, как извлекать и использовать вложенный список из R с известной структурой без повторного копирования частей списка. Пример небольшого кода (со встроенным R-кодом), похоже, работает (cout используется для отладки).Извлечь параметры из списка с помощью Rcpp

Список rL, полученный из R, может быть очень большим, поэтому я не хочу перераспределять память (копировать части rL). Выполняют ли текущие коды копирования частей rL?

Лучший Lars

#include <Rcpp.h> 
#include <iostream> 
using namespace Rcpp; 
using namespace std; 

// [[Rcpp::export]] 
SEXP testing(const List rL) { 
    List L(rL); 
    SEXP sL2(L["L2"]); 
    List L2(sL2); 

    SEXP sStateGrpL2(L2["stateGroups"]); 
    List stateGrpL2(sStateGrpL2); 
    SEXP sStateAllocL2(L2["stateAlloc"]); 
    CharacterVector stateAllocL2(sStateAllocL2); 

    SEXP sActionGrpL2(L2["actionGroups"]); 
    List actionGrpL2(sActionGrpL2); 
    SEXP sActionAllocL2(L2["actionAlloc"]); 
    List actionAllocL2(sActionAllocL2); 

    vector<string> stateLabels; 
    vector<string> actionLabels; 
    CharacterVector actionNames; 

    for(int n2 = 0; n2< as<int>(L2["stages"]); n2++) { 
     stateLabels = as< vector<string> >(stateGrpL2[as<string>(stateAllocL2[n2])]); 
     int s2Size = stateLabels.size(); 
     SEXP sAllocA(actionAllocL2[n2]); 
     List allocA(sAllocA); 
     actionNames = as<CharacterVector>(allocA[0]); 
     cout << "stage:" << n2 << " sN:" << as<string>(stateAllocL2[n2]) << "\n"; 
     for (int s2=0; s2<s2Size; ++s2) { 
     cout << " s:" << stateLabels[s2] << " aN:" << actionNames[s2] << "\n"; 
     actionLabels = as< vector<string> >(actionGrpL2[ as<string>(actionNames[s2]) ]); 
     int a2Size = actionLabels.size(); 
     for (int a2=0; a2<a2Size; ++a2) { 
      cout << " a:" << actionLabels[a2] << "\n"; 
     } 
     } 
    } 

    return wrap(0); 
} 


/*** R 
L <- list(L2=list(stages=2, 
        stateGroups=list(s1Grp=c("a","b","c"),s2Grp=c("d","e")), 
        stateAlloc = c(rep("s1Grp",1),rep("s2Grp",1)), 
        actionGroups = list(a1Grp=c("terminate","keep"), a2Grp=c("finish")), 
        actionAlloc = list(list(rep("a1Grp",3)), 
             list(c("a1Grp","a2Grp")) 
             ) 
        ) 
    ) 
testing(L) 
*/ 
+0

Передайте по ссылке '&', если вы имеете в виду не изменять L? Тем не менее ... Что вы пытаетесь сделать? –

+0

rL - компактное представление состояний в иерархическом процессе принятия решений Маркова. Мне нужен C++, поскольку в основном, поскольку вложенные для циклов очень медленные в R. – Relund

ответ

3

Вы пишете:

Список Р.Л. может быть очень большой, так что я не хочу, чтобы использовать новую память (копия части Rl). Это способ сделать это?

В значительной степени (насколько я могу судить с первого взгляда на ваш код).

Весь обмен с R использует SEXP типы где P стенды для указателя - эти мелкие прокси-объекты, которые будут не скопированные. Он использует/повторно использует память объекта R.

Так что если вы профиль/профиль памяти, то он должен вести себя аналогично для N = 10 и N = 1e5. Но доказательство в пудинг ...

+0

Спасибо. Это также было моей догадкой, но я был немного уверен, как работает <>. Еще один вопрос: «Список L2 (wrap (L [" L2 "]));' не будет таким же, поскольку wrap сделает копию? – Relund

+0

Но если вы вернетесь, это тип R (через тип Rcpp), тогда вам может не понадобиться обертка. –

1

Несколько вещей:

  • тест n2< as<int>(L2["stages"]) Петля как трудно читать и неэффективной, так как она рассчитана на каждой итерации. Вы должны определенно сделать это только один раз.

  • Все ваши as< vector<string> > создают глубокие копии и не используют кеш строки строки. Не можете ли вы использовать CharacterVector?

+0

Выключить причину Я буду менять петлю. Мне нужна строка для ввода функции. Однако я могу изменить тип на CharacterVector. благодаря – Relund

Смежные вопросы