循环在Rcpp中的嵌套列表

时间:2017-11-02 09:39:04

标签: r 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";
}

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

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

2 个答案:

答案 0 :(得分:2)

错误

我认为错误正在发生,因为当您的子列表没有名称时,您正在尝试打印子列表的名称:

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

  

Writing R Extensions手册提供了扩展R的文档黄金标准,强烈建议使用Rprintf和REprintf作为输出(来自C / C ++代码)。关键原因是它们与R本身维护的通常输出和错误流相匹配。

     

事实上,在运行R CMD检查时会标记std :: cout和std :: cerr(在标准C ++代码中很常见),并且在上传到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";
        }
    }
}

当你在示例对象上从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而忽略了结束的大括号。

答案 1 :(得分:0)

我有以下嵌套列表,我想使用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

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

就像duckmayr提到的那样,您提供的列表没有任何名称,并且您使用了一个未显示的名为integer_names_get的函数。