在 Rcpp 中循环嵌套列表

N08*_*N08 2 r rcpp

我有以下嵌套列表,我想使用 Rcpp 循环:

nested_list <- list("a"=list("a_a","a_b","a_c"), 
                    "b"=list("b_a", "b_b", "b_c"))
Run Code Online (Sandbox Code Playgroud)

这是我的尝试:

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


// [[Rcpp::export]]
CharacterVector names_get( Rcpp::List y ){
  return y.names() ;
}

// [[Rcpp::export]]
void output( Rcpp::List y ){

  for(const auto &i : names_get(y))
  {
    Rcpp::List tmp = y[std::string(i)];

    for(const auto &j : integer_names_get(tmp))
      std::cout << j << "\n";
}
Run Code Online (Sandbox Code Playgroud)

它编译得很好,但是当我运行它时output(nested_list)出现错误Error in output(nested_list) : not compatible with STRSXP

这个错误是什么意思,它在哪里/为什么出现?

duc*_*ayr 5

错误

我相信发生错误是因为您在子列表没有名称时尝试打印子列表的名称:

names(nested_list)
names(nested_list[[1]])
str(nested_list)

> names(nested_list)
[1] "a" "b"
> names(nested_list[[1]])
NULL
> str(nested_list)
List of 2
 $ a:List of 3
  ..$ : chr "a_a"
  ..$ : chr "a_b"
  ..$ : chr "a_c"
 $ b:List of 3
  ..$ : chr "b_a"
  ..$ : chr "b_b"
  ..$ : chr "b_c"
Run Code Online (Sandbox Code Playgroud)

您拥有的是一个包含两个列表的列表,每个列表都有三个未命名的元素,每个元素都是一个长度为 1 的字符向量。

输出

一个不相关但仍然重要的问题是,在使用 Rcpp 时,您应该真正使用Rcout而不是cout; 来自Rcpp 画廊

就扩展 R 而言,提供文档的黄金标准的编写 R 扩展手册强烈建议使用 Rprintf 和 REprintf 进行输出(来自 C/C++ 代码)。关键原因是这些与 R 本身维护的常用输出和错误流相匹配。

事实上,使用 std::cout 和 std::cerr(在标准 C++ 代码中很常见)在运行 R CMD 检查时被标记,上传到 CRAN 时不再允许。

多亏了 Jelmer Ypma 的一个初始补丁,它已经被重新设计和扩展,我们有设备 Rcout(用于标准输出)和 Rcerr(用于标准错误),它们拦截输出并将其重定向到 R。

修订代码

如果您确实正在使用类似的对象nested_list并需要获取诸如 的元素"a_a",则可以尝试以下操作(可能不是最优雅的解决方案,但可以完成工作):

#include <Rcpp.h>

using namespace Rcpp;

// [[Rcpp::export]]
void output(List x) {
    int n = x.size();
    for ( int i = 0; i < n; ++i ) {
        List sublist = x[i];
        int m = sublist.size();
        for ( int j = 0; j < m; ++j ) {
            CharacterVector sublist_element = sublist[j];
            Rcout << sublist_element << "\n";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

其中,当在您的示例对象上从 R 调用时,会给出以下内容:

> output(nested_list)
"a_a"
"a_b"
"a_c"
"b_a"
"b_b"
"b_c"
Run Code Online (Sandbox Code Playgroud)

但是,如果您确实正在使用其子列表具有名称的嵌套列表,如下所示:

# Make a nested list with sub-element names:
nested_list2 <- list("a"=list("a_a"=1,"a_b"=2,"a_c"=3), 
                     "b"=list("b_a"=1, "b_b"=2, "b_c"=3))
Run Code Online (Sandbox Code Playgroud)

您的函数为我提供了以下输出(没有错误):

a_a
a_b
a_c
b_a
b_b
b_c
Run Code Online (Sandbox Code Playgroud)

但只有在我修复了一个错字之后,您才调用integer_names_get而不是names_get并省略了结尾的大括号。