如何检查列表是否递归包含列表

时间:2018-07-14 22:15:48

标签: rcpp

我在R中有一个函数,该函数以递归方式构建深度不同的列表的列表。输出node可能是

node<-list(right=(0))

node<-list(right=list(right=0))

在Rcpp中,我想以递归方式构造列表,并返回整数成员,在这种情况下为0。

我的问题是检查node是否具有命名成员right

library(Rcpp)

cppFunction(
'
int predict(List node){
   if(node["right"]){
     return predict(node["right"]);
   }
   else{
     return node;
   }
 }
}
'
)

我看过Dynamic Wrapping来检查类型并使用switch / case,但是似乎不喜欢命名列表。

2 个答案:

答案 0 :(得分:1)

您只需获取名称并检查是否有元素right

以下代码应该起作用:

library(Rcpp)

cppFunction(
  '
  int predict(List node) {
    std::vector<std::string> list_names = node.names();
    if (std::find(list_names.begin(), list_names.end(), "right") != list_names.end()) {
      if (TYPEOF(node["right"]) == REALSXP) {
        return node["right"];
      } else {
        return predict(node["right"]);
      }
    } else {
      return -1;
    }
  }
  '
)

结果

> node<-list(right=(0))
> predict(node)
[1] 0
> node<-list(right=list(right=0))
> predict(node)
[1] 0

答案 1 :(得分:1)

尝试使用子集(例如if(node["right"]),将触发以下错误:

Error in predict_bad(node) : Not compatible with requested type: [type=list; target=logical].

要在List*Vector中搜索命名元素,请使用.containsElementNamed("name")成员函数。

例如,我们有:

#include<Rcpp.h>

// [[Rcpp::export]]
Rcpp::List predict_list(Rcpp::List node){

    // Check if name is present
    if(node.containsElementNamed("right")) {
        return predict_list(node["right"]);
    }

    return node;
}

注意,这里我们返回一个Rcpp::List,例如

node1 = list(right = list(right = 0))  
predict_list(node1)
# [[1]]
# [1] 0

要仅获取整数,我们必须首先子集列表并投射为适当的类型。第二个组成部分,如果足够技巧,可以允许Rcpp automagic处理转换。 (感谢强国透露了先前的答案,不是的位置必须受到限制。)

#include<Rcpp.h>

// [[Rcpp::export]]
int predict_node_val(Rcpp::List node) {

    // Check if name is present
    if(node.containsElementNamed("right")) {

        // Check if element isn't a list.
        switch(TYPEOF(node["right"])) {
        case REALSXP:
        case INTSXP:
            return node["right"];
        default: // Keep going down the tree
            return predict_node_val(node["right"]);
        }

    }

    // Quiet compiler by providing a final output case
    return -1;
}

输出:

node1 = list(right = list(right = 0))  
node2 = list(right = 0)  
predict_node_val(node1)
# [1] 0
predict_node_val(node2)
# [1] 0

上面有一些假设...首先,我们将始终具有基于类型的列表架构。第二个是我们要检索的值始终列为"right"。第三

相关问题