【问题标题】:Rust - return a mutable reference to an element in Vec owned by a structRust - 返回对结构拥有的 Vec 中元素的可变引用
【发布时间】:2021-03-26 21:59:42
【问题描述】:

这是我的结构:

pub(crate) struct Graph {
    outbound: HashMap<isize, Vec<isize>>,
    inbound: HashMap<isize, Vec<isize>>,
    edges: Vec<Edge>,
}

以及我尝试过的:

fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
    let mut edges = self
        .edges
        .iter_mut()
        .filter(|edge| edge.get_from() == from_id && edge.get_to() == to_id)
        .collect::<Vec<_>>();
    match edges.len() {
        0 => Err(GraphError(format!(
            "edge from {} to {} does not exist",
            from_id, to_id
        ))),
        1 => Ok(edges[0]),
        _ => panic!(
            "wrong graph structure - edge from {} to {} exists multiple times",
            from_id, to_id
        ),
    }
}

问题出在这里:Ok(edges[0])

cannot return value referencing local variable "edges" 失败

我知道edges 归当前函数所有,我无法返回对它的引用,因为它超出了范围,但是返回对“边缘”中元素的可变引用的更好方法是什么Vec(结构的)基于某些条件?

【问题讨论】:

  • 请尝试创建minimal reproducible example。我认为edges.pop() 会在这里工作而不是edges[0],但是,如果不能对其进行测试,就很难确定。
  • 考虑使用邻接矩阵而不是邻接列表 - 矩阵缩放为 n^2,但列表对于小型 n / 密集图有 很多 开销,并且也是访问速度要慢得多。如果您确实有非常大的稀疏图,则可能有一个稀疏矩阵库可以帮助您保持合理的内存使用。当然,您也可以只使用petgraph,这取决于您的具体需求。
  • @trentcl 效率不是我的问题,我只想将该元素作为可变引用:) 但它不会以这种方式编译,我正在寻找替代方案
  • 不是直接获取可变引用,而是找到边的索引,然后返回可变引用。

标签: rust


【解决方案1】:

我建议使用:

    fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
        self.edges.iter_mut()
            .find(|edge| edge.get_from() == from_id && edge.get_to() == to_id)
            .ok_or(GraphError(format!("edge from {} to {} does not exist", from_id, to_id)))
    }

它会跳过您的“错误的图形结构检查”,但如果需要,您可以使用

fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
    let mut edges_matching = self.edges.iter_mut()
        .filter(|edge| edge.get_from() == from_id && edge.get_to() == to_id);

    let edge = edges_matching.next()
        .ok_or(GraphError(format!("edge from {} to {} does not exist", from_id, to_id)));

    assert_eq!(edges_matching.count(), 0,
               "wrong graph structure - edge from {} to {} exists multiple times",
               from_id, to_id);

    edge
}

似乎问题可能源于edges[0] 最终调用SliceIndex::index,它基本上返回一个Option&lt;&amp;&amp;mut Edge&gt;,其中第一个&amp; 实际上是对当前函数的引用。

trendcl 是对的,edges.pop() 也可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多