如何判断我是否已处理节点

How to tell if I've already processed a node

本文关键字:是否 处理 节点 何判断 判断      更新时间:2023-10-16

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

这类似于从文档中检索yaml-cpp中的锚点和别名字符串,但是尽管该功能足以解决我的问题,但这不是必需的 - 例如,如果我可以根据节点的内部地址以某种方式获得哈希,那就好了。

我正在做的昂贵的事情是计算每个节点的哈希值,包括它自己和它的子节点。

这是一个补丁,似乎可以满足我的需要。请谨慎操作。

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();
    }
  };
}

您可以通过operator ==Node::is来检查节点身份,例如:

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

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

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