1

我有一个petgraph::Graph结构,我通过赋予每个节点权重 a 来强加一个树结构,parent_edge_idx这是Option<EdgeIdx>从其父节点连接到自身的边的一个。

我需要遍历一个节点的孩子。我需要连接边的边权重子节点的权重。

我想将该迭代分解为一个辅助函数,该函数返回对Iterator<Item = (EdgeIdx, NodeIdx)>. 我想免费做这个;因为我必须借用self.search_tree才能做到这一点,所以迭代器仅在self.

  1. 这是要编写的合理函数吗?
  2. 这个函数可以写吗?

任何门控功能都可以;我在夜间。

fn children<'a>(
    &'a mut self,
    node_idx: NodeIdx,
) -> &'a impl Iterator<Item = (EdgeIdx, NodeIdx)> {
    &self.search_tree.neighbors(node_idx).map(|child_idx| {
        let node = self.search_tree.node_weight(child_idx).unwrap();
        let edge_idx = node.parent_edge_idx.unwrap();
        (edge_idx, child_idx)
    })
}
4

1 回答 1

4

如何返回迭代器已经包含在这个问题中。

  1. 请注意,您不需要返回引用:您想直接返回一个迭代器,因此如果我们删除&方法体和返回类型中的第一个,那就更接近我们需要的了。

  2. 我们将使用impl Iterator这样我们就不必准确命名实际的迭代器类型。请注意(下面的代码)我们需要使用impl Iterator<..> + 'a语法,这意味着(匿名)迭代器包含至少在生命周期内有效的引用'a

  3. 我们不能&mut self在这里使用!请注意,我们需要借用self.search_tree两次:一次用于.neighbors()迭代器,一次用于包中使用的self.search_treethat 。多次借用与可变引用不兼容。map

  4. 我们将move作为捕获模式放在闭包上,以便它self直接捕获引用,而不是通过引用(这很重要,因为我们可以返回迭代器和闭包。

  5. Petgraph 是特定的,但我们替换g.node_weight(node_index).unwrap()为 just &g[node_index]which 是等价的,但后者更容易阅读。

这是您的代码的复制品,但对 1-5 进行了修改以使其编译:

#![feature(conservative_impl_trait)]
extern crate petgraph;

use petgraph::Graph;
use petgraph::graph::{NodeIndex, EdgeIndex};

struct Foo {
    search_tree: Graph<Node, i32>,
}

struct Node {
    parent_edge_idx: Option<EdgeIndex>,
}

impl Foo {
    fn children<'a>(&'a self, node_idx: NodeIndex)
        -> impl Iterator<Item = (EdgeIndex, NodeIndex)> + 'a
    {
        self.search_tree.neighbors(node_idx).map(move |child_idx| {
            let node = &self.search_tree[child_idx];
            let edge_idx = node.parent_edge_idx.unwrap();
            (edge_idx, child_idx)
        })
    }
}
于 2018-03-11T19:45:37.517 回答