Изменять поле элемента Vec, зацикливая поле другого элемента в том же Vec - PullRequest
0 голосов
/ 19 сентября 2018

Я пишу структуру данных Trie в Rust для реализации алгоритма Aho-Corasick.Структура TrieNode представляет узел и выглядит следующим образом:

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

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

Я использую ту же стратегию, что и арена поколений, для реализации дерева, где все узлы хранятся в одном 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()?

1 Ответ

0 голосов
/ 19 сентября 2018

Разделить фрагмент:

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);
    }
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...