我在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,但是似乎不喜欢命名列表。
答案 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"
。第三