Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Yaml cpp 如何在yaml cpp中合并节点_Yaml Cpp - Fatal编程技术网

Yaml cpp 如何在yaml cpp中合并节点

Yaml cpp 如何在yaml cpp中合并节点,yaml-cpp,Yaml Cpp,我有两个节点对象,如下所示: school: grade: class: name: bob school: grade: class: age: 18 school: grade: class: name: bob age: 18 我想合并它,结果如下: school: grade: class: name: bob school: grade: class: a

我有两个节点对象,如下所示:

school:
  grade:
    class:
     name: bob
school:
  grade:
    class:
      age: 18
school:
  grade:
    class:
      name: bob
      age: 18
我想合并它,结果如下:

school:
  grade:
    class:
     name: bob
school:
  grade:
    class:
      age: 18
school:
  grade:
    class:
      name: bob
      age: 18
如何合并它?当不知道节点大小和深度时。

以下是我的尝试:

#包括
内联常量YAML::节点和cnode(常量YAML::节点和n){
返回n;
}
YAML::节点合并\节点(YAML::节点a,YAML::节点b)
{
如果(!b.IsMap()){
//若b不是映射,则合并结果为b,除非b为空
返回b.IsNull()?a:b;
}
如果(!a.IsMap()){
//如果a不是映射,则合并结果为b
返回b;
}
如果(!b.size()){
//如果a是映射,而b是空映射,则返回a
返回a;
}
//使用与a相同的映射创建新映射“c”,并与b合并
自动c=YAML::Node(YAML::NodeType::Map);
用于(自动n:a){
if(n.first.IsScalar()){
常量std::string&key=n.first.Scalar();
自动t=YAML::Node(cnode(b)[键]);
if(t){
c[n.first]=合并节点(n.second,t);
继续;
}
}
c[n.first]=n.second;
}
//添加“b”中尚未在“c”中的映射
用于(自动n:b){
如果(!n.first.IsScalar()| |!cnode(c)[n.first.Scalar()]){
c[n.first]=n.second;
}
}
返回c;
}

对于非标量键,我选择忽略节点等价性。请注意,此版本不修改
a
。它返回一个新的映射
c
,它是
b
a
的合并。
b
中的值将替换
c
映射中
a
中相同键控的非映射值。

我发现md5i的答案存在一个问题,即它不会合并第二个节点的唯一子节点。我的修复程序在节点b的for循环中再次调用该函数(我将其重命名为override节点)。我还将所有内容都设置为常量,因为我没有在这里编辑任何内容,所以我不必强制转换它。我还强调了第二个节点正在覆盖另一个节点的事实

const YAML::Node mergeNodes(const YAML::Node& defaultNode, const YAML::Node& overrideNode)
{
  if (!overrideNode.IsMap()) {
    // If overrideNode is not a map, merge result is overrideNode, unless overrideNode is null
    return overrideNode.IsNull() ? defaultNode : overrideNode;
  }
  if (!defaultNode.IsMap()) {
    // If defaultNode is not a map, merge result is overrideNode
    return overrideNode;
  }
  if (!defaultNode.size()) {
    return YAML::Node(overrideNode);
  }
  // Create a new map 'newNode' with the same mappings as defaultNode, merged with overrideNode
  auto newNode = YAML::Node(YAML::NodeType::Map);
  for (auto node : defaultNode) {
    if (node.first.IsScalar()) {
      const std::string& key = node.first.Scalar();
      if (overrideNode[key]) {
        newNode[node.first] = mergeNodes(node.second, overrideNode[key]);
        continue;
      }
    }
    newNode[n.first] = node.second;
  }
  // Add the mappings from 'overrideNode' not already in 'newNode'
  for (auto node : overrideNode) {
    if (!node.first.IsScalar()) {
      const std::string& key = node.first.Scalar();
      if (defaultNode[key]) {
        newNode[node.first] = mergeNodes(defaultNode[key], node.second);
        continue;
      }
    }
    newNode[node.first] = node.second;
  }
  return YAML::Node(newNode);
}

这可能不会有任何好处,但它将从节点b/覆盖节点获取节点,即使它们在节点a/默认节点中没有实例。

为什么使用
cnode
函数?需要调用
操作符[]
方法的常量版本,因为非常量版本修改对象(就像在
std::vector
中一样。这看起来比到处打字更干净。