如何判断我是否已经处理过一个节点

时间:2013-11-02 14:43:00

标签: c++ yaml yaml-cpp

我正在处理由许多冗余值组成的大型文件(使用YAML的锚点和引用)。我对每个结构的处理都很昂贵,我想检测一下我是否正在查看我已经处理过的锚的引用。在Python(使用python-yaml)中,我通过简单地构建一个由id(node)键入的字典来实现这一点。但是,由于yaml-cpp使用Node作为引用类型,因此这似乎不起作用。有什么建议吗?

这类似于Retrieve anchor & alias string in yaml-cpp from document,但是虽然这个功能足以解决我的问题,但它不是必要的 - 如果我能以某种方式得到基于节点内部地址的哈希,例如,没关系。

我正在做的昂贵的事情是计算每个节点的散列,包括它自己及其子节点。

2 个答案:

答案 0 :(得分:1)

这是一个看起来像我需要的补丁。谨慎行事。

diff -nr include/yaml-cpp/node/detail/node.h new/yaml-cpp-0.5.1/include/yaml-cpp/node/detail/node.h
a13 1
#include <boost/functional/hash.hpp>
a24 1
            std::size_t identity_hash() const { return boost::hash<node_ref*>()(m_pRef.get()); }
diff -nr /include/yaml-cpp/node/impl.h new/yaml-cpp-0.5.1/include/yaml-cpp/node/impl.h
a175 5
    inline std::size_t Node::identity_hash() const
    {
    return m_pNode->identity_hash();
    }

diff -nr include/yaml-cpp/node/node.h new/yaml-cpp-0.5.1/include/yaml-cpp/node/node.h
a55 2
        std::size_t identity_hash() const;

然后我可以使用下面的代码来使用YAML :: Node作为密钥来创建一个unordered_map。

namespace std {
  template <>
  struct hash<YAML::Node> {
    size_t operator()(const YAML::Node& ss) const {
      return ss.identity_hash();
    }
  };
}

答案 1 :(得分:0)

您可以按operator ==Node::is检查节点标识,例如:

Node a = ...;
process(a);
Node b = ...;
if (!a.is(b)) {
  process(b);
}

我认为这并不完美 - 如果您尝试在大量节点上执行此操作,则检查必须为O(n)。

如果您需要更多,请在项目页面上提交问题。