如何递归检查列表是否包含列表
how to check if list contains lists recursively
我在 R 中有一个函数可以递归地构建不同深度列表的列表。输出 node
可能是
node<-list(right=(0))
或
node<-list(right=list(right=0))
在 Rcpp 中,我想构建一个递归解构列表和 return 整数成员,在本例中为 0。
我的问题是检查 node
是否有命名成员 right
library(Rcpp)
cppFunction(
'
int predict(List node){
if(node["right"]){
return predict(node["right"]);
}
else{
return node;
}
}
}
'
)
我看过 Dynamic Wrapping 检查类型并使用 switch/case,但它似乎不喜欢命名列表。
您可以只获取名称并检查是否有元素 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
尝试使用子集检查命名值是否存在,例如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"
。第三个
我在 R 中有一个函数可以递归地构建不同深度列表的列表。输出 node
可能是
node<-list(right=(0))
或
node<-list(right=list(right=0))
在 Rcpp 中,我想构建一个递归解构列表和 return 整数成员,在本例中为 0。
我的问题是检查 node
是否有命名成员 right
library(Rcpp)
cppFunction(
'
int predict(List node){
if(node["right"]){
return predict(node["right"]);
}
else{
return node;
}
}
}
'
)
我看过 Dynamic Wrapping 检查类型并使用 switch/case,但它似乎不喜欢命名列表。
您可以只获取名称并检查是否有元素 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
尝试使用子集检查命名值是否存在,例如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"
。第三个