You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在petgraph的GraphMap中移除指定节点的所有出边?编译报错求助

解决petgraph GraphMap中移除指定节点所有出边的编译错误

需求与尝试代码

需要移除有向GraphMap中指定节点的所有出边,尝试的代码如下:

use petgraph::{graphmap::GraphMap, visit::EdgeRef, Directed, Direction};
fn main() {
    let mut g = GraphMap::<MyNode, u32, Directed>::new();  
    let node1 = MyNode { value1: 1, value2: 1 };
    let node2 = MyNode { value1: 2, value2: 2 };

    g.add_node(node1);
    g.add_node(node2);
    g.add_edge(node1, node2, 1);
    
    g.edges_directed(node1, Direction::Outgoing).for_each(|edge| {
        g.remove_edge(edge.source(), edge.target());
    });      

    println!("{:?}", g);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MyNode {
    pub value1: u32,
    pub value2: u32,
}

编译错误

代码无法通过编译,报错信息如下:

Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `g` as mutable because it is also borrowed as immutable
  --> src/main.rs:11:59
   |
11 |     g.edges_directed(node1, Direction::Outgoing).for_each(|edge| {
   |     -                                            -------- ^^^^^^ mutable borrow occurs here
   |     |                                            |
   |     immutable borrow occurs here                 immutable borrow later used by call
12 |         g.remove_edge(edge.source(), edge.target());
   |         - second borrow occurs due to use of `g` in closure

问题原因

edges_directed方法返回的迭代器持有GraphMap的不可变引用,而闭包中调用remove_edge需要获取GraphMap的可变引用。Rust的借用规则禁止同一时间对同一值同时存在不可变和可变引用,因此编译失败。

解决方案

先将所有需要移除的边的(源节点,目标节点)对收集到一个临时向量中,待迭代器的不可变借用结束后,再遍历这个向量移除边:

use petgraph::{graphmap::GraphMap, visit::EdgeRef, Directed, Direction};

fn main() {
    let mut g = GraphMap::<MyNode, u32, Directed>::new();  
    let node1 = MyNode { value1: 1, value2: 1 };
    let node2 = MyNode { value1: 2, value2: 2 };

    g.add_node(node1);
    g.add_node(node2);
    g.add_edge(node1, node2, 1);
    
    // 收集所有待移除的边的节点对
    let edges_to_remove: Vec<_> = g.edges_directed(node1, Direction::Outgoing)
        .map(|edge| (edge.source(), edge.target()))
        .collect();
    
    // 遍历移除边
    for (source, target) in edges_to_remove {
        g.remove_edge(source, target);
    }      

    println!("{:?}", g);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MyNode {
    pub value1: u32,
    pub value2: u32,
}

这种方式先通过不可变借用完成边信息的收集,此时迭代器的借用已经释放,后续的可变借用修改GraphMap完全符合Rust的借用规则,代码可以正常编译运行。

内容的提问来源于stack exchange,提问作者Ron Slosberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:43:12