在 Rcpp 中循环嵌套列表

Looping over nested list in Rcpp

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

nested_list <- list("a"=list("a_a","a_b","a_c"), 
                    "b"=list("b_a", "b_b", "b_c"))

这是我的尝试:

#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";
}

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

这个错误是什么意思,where/why它出现了吗?

错误

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

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"

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

Rcout

一个无关但重要的问题是,在使用 Rcpp 时,你应该真正使用 Rcout 而不是 cout;来自 the Rcpp Gallery:

The Writing R Extensions manual, which provides the gold standard of documentation as far as extending R goes, strongly suggests to use Rprintf and REprintf for output (from C/C++ code). The key reason is that these are matched to the usual output and error streams maintained by R itself.

In fact, use of std::cout and std::cerr (as common in standard C++ code) is flagged when running R CMD check and no longer permitted when uploading to CRAN.

Thanks to an initial patch by Jelmer Ypma, which has since been reworked and extended, we have devices Rcout (for standard output) and Rcerr (for standard error) which intercept output and redirect it to 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";
        }
    }
}

当从 R 调用您的示例对象时,会给出以下结果:

> output(nested_list)
"a_a"
"a_b"
"a_c"
"b_a"
"b_b"
"b_c"

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

# 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))

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

a_a
a_b
a_c
b_a
b_b
b_c

但只有在我修正了一个拼写错误之后,您调用 integer_names_get 而不是 names_get 并遗漏了结尾的大括号。

I have the following nested list that I want to loop over using Rcpp

只是为了添加一个更优雅的解决方案,您可以使用这些函数来打印嵌套列表的名称或嵌套列表的元素:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void print_char_ele(List x) {
  for(auto sub_list : x)
    for(auto ele : List(sub_list)) 
      for(auto ele_i : CharacterVector(ele))
        Rcout << ele_i << '\n';
}

// [[Rcpp::export]]
void print_names(List x) {
  for(auto sub_list : x)
    for(auto nam : CharacterVector(List(sub_list).names())) 
      Rcout << nam << '\n';
}

这里是使用两个函数的结果

nested_list <- list("a" = list("a_a" = "x" , "a_b" = "y" , "a_c" = "z" ), 
                    "b" = list("b_a" = "xx", "b_b" = "yy", "b_c" = "zz"))

print_char_ele(nested_list)
#R> x
#R> y
#R> z
#R> xx
#R> yy
#R> zz
print_names(nested_list)
#R> a_a
#R> a_b
#R> a_c
#R> b_a
#R> b_b
#R> b_c

What does this error mean and where/why does it appear?

正如 duckmayr 提到的,您提供的列表没有任何名称,并且您使用了一个名为 integer_names_get 的函数,但您没有显示。