通过引用遍历节点的惯用方式

Posted

技术标签:

【中文标题】通过引用遍历节点的惯用方式【英文标题】:Idiomatic way to traverse nodes by reference 【发布时间】:2013-01-31 16:48:52 【问题描述】:

以一个字符串开头,该字符串表示我要从中检索数据的节点的路径,例如“a.b.c”。目前,我用来遍历节点层次结构以到达该节点的代码看起来像这样(可能无法编译,但你明白了):

string keyPath("a.b.c");
vector<string> keyPieces(split(keyPath, "."));

const YAML::Node *currNode = &rootNode;
for_each(begin(keyPieces), end(keyPieces), [&](const string &key)

    // for simplicity, ignore indexing on a possible scalar node
    // and using a string index on a sequence node
    if ((*currNode)[key])
    
        currNode = &((*currNode)[key]);
    
);

// assuming a valid path, currNode should be pointing at the node
// described in the path (i.e. currNode is pointing at the "c" node)

上面的代码似乎可以正常工作,但我想知道是否有更好的方法来进行节点横向分配。使用直接节点分配 (currNode = currNode[key]),而不是 (currNode = &amp;((*currNode)[key])) 的指针/地址,似乎最终会在节点之间创建引用,而不是从一个节点遍历到下一个节点。

是否有一种“更简洁”或更惯用的方式来实现这一点?

【问题讨论】:

【参考方案1】:

现在没有办法做到这一点(这是一个我没有想到的用例),但这是个好主意。我已经提交了一个错误 (http://code.google.com/p/yaml-cpp/issues/detail?id=189)。

【讨论】:

【参考方案2】:

我在做类似的事情,发现这个功能是前一段时间添加的,称为Node::reset()

所以,

string keyPath("a.b.c");
vector<string> keyPieces(split(keyPath, "."));

YAML::Node currNode = rootNode;
for_each(begin(keyPieces), end(keyPieces), [&](const string &key)

    if (currNode[key])
    
        currNode.reset(currNode[key]);
    
);

应该按预期工作。

【讨论】:

确实,这是 Jesse Beder 回答的结果。不幸的是,Google 代码结尾意味着链接会中断,但这里有一个 Internet Archive link。 currNode 是 const,但您正在调用 reset(),它是非常量(丢弃限定符),不应该编译。我也没有看到“currNode.reset(currNode[key])”和“currNode = currNode[key]”之间的区别,即使它确实编译了。 是的,删除了 const。对于第二个语句:但这正是需要重置的问题所在:currnode=currnode[key] 也会修改根节点

以上是关于通过引用遍历节点的惯用方式的主要内容,如果未能解决你的问题,请参考以下文章

一次循环遍历 Javascript 数组多个元素的惯用方法是啥?

通过两种深度优先遍历方式重建二叉树或者得到其余一种遍历方式

jquery json遍历节点的问题

jquery中都有哪些方法可以遍历节点

for foreach iterator 三种遍历方式的比较

数据结构-遍历序列求二叉树