Как я могу сопоставить и изменить элемент в Vec? - PullRequest
0 голосов
/ 07 октября 2019

У меня есть Vec опционально HashSet с. Если слот None, я хочу выделить HashSet и сохранить его в Vec. В обоих случаях я хочу добавить к HashSet.

Я понимаю, на что жалуется ошибка компилятора, но не на то, какой синтаксис заставит проблему исчезнуть. Предлагаемое изменение компилятора также не компилируется, как и любой другой синтаксис, который я пробую. Как мне сопоставить ячейку Vec, проверить, является ли она None, выделить Some<HashSet>, если она None, или просто получить доступ к HashSet, если она существует, и в обоих случаях добавить новое целое число длянабор?

КОД:

use std::collections::HashSet;
use std::collections::BTreeSet;
use std::iter::FromIterator;
use maplit;

pub struct Graph {
    outgoing_edges : Vec<Option<HashSet<usize>>>,
    incoming_edges : Vec<Option<HashSet<usize>>>
}

impl Graph {
    pub fn new(node_count : usize) -> Self {
        Graph {
            outgoing_edges : vec!(None; node_count),
            incoming_edges : vec!(None; node_count)
        }
    }

    /// Add a directional edge that starts at `from_node` and points to `to_node`.
    pub fn add_edge(&mut self, from_node : usize, to_node : usize) {
        match &self.outgoing_edges[from_node] {
            Some(mut set) => { set.insert(to_node); () },
            None => { self.outgoing_edges[from_node] = Some(hashset!{ to_node }); () }
        }
        match &self.incoming_edges[to_node] {
            Some(mut set) => { set.insert(from_node); () },
            None => { self.incoming_edges[to_node] = Some(hashset!{ from_node }); () }
        }
    }
}

ОШИБКА:

(Номера строк взяты из моего исходного файла, а не фрагмент короткого кода. Сообщение об ошибке появилось до того, как я добавил амперсанд для заимствования, как показано выше, но это изменение кода не сработало.)

error[E0507]: cannot move out of index of `std::vec::Vec<std::option::Option<std::collections::HashSet<usize>>>`
  --> src\graph\mod.rs:46:15
   |
46 |         match self.outgoing_edges[from_node] {
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider borrowing here: `&self.outgoing_edges[from_node]`
47 |             Some(mut set) => { set.insert(to_node); () },
   |                  -------
   |                  |
   |                  data moved here
   |                  move occurs because `set` has type `std::collections::HashSet<usize>`, which does not implement the `Copy` trait

Ответы [ 2 ]

3 голосов
/ 07 октября 2019

Вместо использования сопоставления с образцом вы можете использовать метод Option::get_or_insert_with(), чтобы создать новый хэш-набор, если требуется, и вернуть ссылку либо на существующий, либо на вновь созданный хеш-набор. Полный код может выглядеть так:

pub fn add_edge(&mut self, from_node: usize, to_node: usize) {
    self.outgoing_edges[from_node]
        .get_or_insert_with(HashSet::new)
        .insert(to_node);
    self.incoming_edges[to_node]
        .get_or_insert_with(HashSet::new)
        .insert(from_node);
}
2 голосов
/ 07 октября 2019

Это довольно просто, вы хотите связать по ссылке:

/// Add a directional edge that starts at `from_node` and points to `to_node`.
pub fn add_edge(&mut self, from_node : usize, to_node : usize) {
    match self.outgoing_edges[from_node] {
        Some(ref mut set) => { set.insert(to_node); },
        None => { self.outgoing_edges[from_node] = Some(hashset!{ to_node }); }
    }
    match self.incoming_edges[to_node] {
        Some(ref mut set) => { set.insert(from_node); },
        None => { self.incoming_edges[to_node] = Some(hashset!{ from_node }); }
    }
}

Или с функцией эргономики сопоставления с образцом под названием режим связывания , вы также можете сделать следующее:

/// Add a directional edge that starts at `from_node` and points to `to_node`.
pub fn add_edge(&mut self, from_node : usize, to_node : usize) {
    match &mut self.outgoing_edges[from_node] {
        Some(set) => { set.insert(to_node); },
        None => { self.outgoing_edges[from_node] = Some(hashset!{ to_node }); }
    }
    match &mut self.incoming_edges[to_node] {
        Some(set) => { set.insert(from_node); },
        None => { self.incoming_edges[to_node] = Some(hashset!{ from_node }); }
    }
}
...