【问题标题】:Mutate a field of a Vec's element while looping over a field of another element in the same Vec在遍历同一 Vec 中另一个元素的字段时改变 Vec 元素的字段
【发布时间】:2018-09-19 09:32:35
【问题描述】:

我正在用 Rust 编写一个 Trie 数据结构来实现 Aho-Corasick 算法。 TrieNode 结构体代表一个节点,如下所示:

use std::collections::{HashMap, HashSet, VecDeque};

struct TrieNode {
    next_ids: HashMap<char, usize>,
    kw_indices: HashSet<usize>,
    fail_id: Option<usize>,
}

我使用与世代竞技场相同的策略来实现 trie,其中所有节点都存储在一个 Vec 中,并使用它们的索引相互引用。在创建所有节点后构建自动机时,我试图在不使用 clone() 方法的情况下使以下代码工作:

fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
    let mut q = VecDeque::new();
    for &i in nodes[0].next_ids.values() {
        q.push_back(i);
        nodes[i].fail_id = Some(0);
    }
    // ...
}

但是借用检查员对此并不满意:

error[E0502]: cannot borrow `*nodes` as mutable because it is also borrowed as immutable
   |
   |             for &i in nodes[0].next_ids.values() {
   |                       -----                    - immutable borrow ends here
   |                       |
   |                       immutable borrow occurs here
   |                 q.push_back(i);
   |                 nodes[i].fail_id = Some(0);
   |                 ^^^^^ mutable borrow occurs here

在不使用昂贵的clone() 方法的情况下,还有什么方法(如果有的话)可以实现上述目标?

【问题讨论】:

标签: rust borrow-checker


【解决方案1】:

分割切片:

fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
    let mut q = VecDeque::new();
    let (first, rest) = nodes.split_first_mut();
    for &i in first.next_ids.values() {
        q.push_back(i);
        if i == 0 {
            first.fail_id = Some(0);
        } else {
            rest[i-1].fail_id = Some(0);
        }
    }
    ...
}

但是,仅克隆 next_ids 可能成本更低:

fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
    let mut q = VecDeque::new();
    let ids: Vec<_> = nodes[0].next_ids.values().cloned().collect();
    for &i in ids {
        q.push_back(i);
        nodes[i].fail_id = Some(0);
    }
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多