【问题标题】:How to tell if I've already processed a node如何判断我是否已经处理了一个节点
【发布时间】:2013-11-02 14:42:59
【问题描述】:

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

这类似于Retrieve anchor & alias string in yaml-cpp from document,但尽管该功能足以解决我的问题,但这不是必需的——例如,如果我能以某种方式获得基于节点内部地址的哈希,那将没事。

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

【问题讨论】:

    标签: c++ yaml yaml-cpp


    【解决方案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();
        }
      };
    }
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      • 我真正需要的是一种专门化 std::hash 的方法,这样我就可以使用 unordered_map,所以不幸的是成对相等不会做太多。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 2020-05-31
      相关资源
      最近更新 更多