简体   繁体   English

向 Rust 中的 HashSet 添加值,并将对它的引用添加到另一个数据结构

[英]Add value to a HashSet in Rust and add a reference to it to another datastructure

I'm trying to return a Vector from a function. This happens in a loop and I need the values to exist outside of the loop.我正在尝试从 function 返回一个 Vector。这发生在一个循环中,我需要这些值存在于循环之外。 Since I perform the return multiple times and I only need the unique values, I thought I use a HashSet for this, in which I insert and then try to get a reference to the value in the next line.由于我多次执行返回并且我只需要唯一值,我想我为此使用了一个 HashSet,我在其中插入然后尝试获取对下一行中值的引用。

I need a reference to the value in multiple other datastructures and don't want to duplicate the actual values.我需要引用多个其他数据结构中的值,并且不想复制实际值。 The values don't need to be mutable.这些值不需要是可变的。

What I tried我试过的

use std::collections::HashSet;
fn main() {
    let mut vec: Vec<&str> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        // This could be a function call, which returns a vector of objects, which should all be
        // stored centrally and uniquely in a HashSet
        books.insert("A Dance With Dragons".to_string());

        let mut reference: &str = books.get("A Dance With Dragons").unwrap();
        // This would be done for multiple "refering" datastructures
        vec.push(reference);
    }
}

What I was expecting我所期待的

Getting a pointer to the String in the HashSet for future use.获取指向 HashSet 中 String 的指针以供将来使用。

What actually happens实际发生了什么

error[E0502]: cannot borrow `books` as mutable because it is also borrowed as immutable
  --> src/main.rs:10:9
   |
10 |         books.insert("A Dance With Dragons".to_string());
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
11 |
12 |         let mut reference: &str = books.get("A Dance With Dragons").unwrap();
   |                                   --------------------------------- immutable borrow occurs here
13 |         // This would be done for multiple "refering" datastructures
14 |         vec.push(reference);
   |         ------------------- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
warning: `set_test` (bin "set_test") generated 2 warnings
error: could not compile `set_test` due to previous error; 2 warnings emitted

I think I'm missing a very obvious solution to this...我想我错过了一个非常明显的解决方案......

Thanks in advance for helping.在此先感谢您的帮助。

You can't do this你不能这样做

use std::collections::HashSet;
fn main() {
    let mut v: Vec<&str> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        // this needs to borrow mutably
        books.insert("A Dance With Dragons".to_string());

        // this reference has to live as long as v
        // so on the second iteration books is still borrowed
        // which means you can't borrow it mutably any more.
        let reference: &str = books.get("A Dance With Dragons").unwrap();
        v.push(reference);
    }

    // v only goes out of scope here
}

You might find success in separating mutation and referencing like this:您可能会在分离突变和引用方面取得成功,如下所示:

fn main() {
    let mut books = HashSet::new();
    for i in 0..5 {
        books.insert("A Dance With Dragons".to_string());
    }

    let v: Vec<&str> = books.iter().collect();
}

Or by using a Rc like pigeonhgands suggests.或者像 pigeonhgands 建议的那样使用Rc

fn main() {
    let mut v: Vec<Rc<str>> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        books.insert(Rc::new("A Dance With Dragons".to_string()));

        // note: this clone is cheap cause it only clones the `Rc` not the whole String.
        let reference = books.get("A Dance With Dragons").unwrap().clone();
        v.push(reference);
    }
}

The issue is that's the value in "book" could be removed and you try to save reference in a vector.问题是“book”中的值可能会被删除,而您尝试将引用保存在向量中。 It is a risk of null pointer.它是 null 指针的风险。

You need to build book in imutable way, like this您需要以不可变的方式构建书籍,就像这样

use std::collections::HashSet;

fn main() {
    let mut vec: Vec<&str> = Vec::new();
    
    let books: HashSet<String> = vec!(
        "A Dance With Dragons".to_string(), 
        "A Dance With Dragons".to_string()).into_iter().collect();
        
    let reference: &str = books.get("A Dance With Dragons").unwrap();
     
    vec.push(reference);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM