简体   繁体   English

Rust - 创建 hashmap,它使用从迭代器存储的部分数据

[英]Rust - create hashmap which uses part of the data it's storing from an iterator

I'm new to rust and am trying to figure out how to create a HashMap of borrowed values from a Vec of data but when I try to do it I get a Vec into a HashMap the ownership model fights me. I'm new to rust and am trying to figure out how to create a HashMap of borrowed values from a Vec of data but when I try to do it I get a Vec into a HashMap the ownership model fights me. I don't know how to accomplish this, maybe I'm just trying something that is against the Rust mentality.我不知道如何做到这一点,也许我只是在尝试一些违背 Rust 心态的东西。

For Example:例如:

struct Data{
    id: String,
    other_value: String,
}

//inside a method somewhere
let data_array = load_data(); // returns a Vec<Data>
let mut hash = HashMap::new(); // HashMap<&String, &Data>

for item in data_array {
    hash.insert(&item.id, &item);
}

As far As I know there should be a way to populate this data in this way as the HashMap would be storing references to the original data.据我所知,应该有办法以这种方式填充这些数据,因为HashMap将存储对原始数据的引用。 Or maybe I've just flat out misunderstood the docs... ¯_(ツ)_/¯或者,也许我只是完全误解了文档...¯_(ツ)_/¯

There key issue here is that you are consuming the Vec .这里的关键问题是您正在使用Vec for loops in Rust work over things that implement IntoIter . Rust 中for循环处理实现IntoIter的事物。 IntoIter moves the Vec into an iterator - the Vec itself no longer exists once this is done. IntoIter将 Vec 移动到迭代器中 - 一旦完成, Vec 本身就不再存在。

Therefore the items that you are looping though disappear at the end of each iteration., so those references end up referencing nonexistent data (dangling references).因此,您正在循环的项目在每次迭代结束时都会消失,因此这些引用最终会引用不存在的数据(悬空引用)。 If you tried to using them, Bad Things Would Happen.如果您尝试使用它们,就会发生坏事。 Rust prevents you shooting yourself in the foot like that, so you get an error telling you that the reference does not live long enough. Rust 可防止您像那样在脚上开枪,因此您会收到错误消息,告诉您参考的寿命不够长。 The solution to make your code compile is very easy.使您的代码编译的解决方案非常简单。 Just add .iter() to the end of the loop, which will iterate through references rather than consume the Vec .只需将.iter()添加到循环的末尾,它将遍历引用而不是消耗Vec

for item in data_array.iter() {
    hash.insert(&item.id, item); //Note we don't need an `&` in front of item
}

So turns out you can borrow the iterator value by borrowing the collection ( Vec ).事实证明,您可以通过借用集合 ( Vec ) 来借用迭代器值。 So the example above turns into:所以上面的例子变成了:

for item in &data_array {
    hash.insert(&item.id, item);
}

Notice the &data_array which turns item from Data type to &Data and allows you to use the borrowed value.请注意&data_arrayitemData类型转换为&Data并允许您使用借来的值。

I'm still relatively new to Rust, so this might not be right, but I think it does what you want, but once and for all -- ie a function that makes it easy to turn a collection into a map using a closure to generate the keys:我对 Rust 还比较陌生,所以这可能不对,但我认为它可以满足您的需求,但一劳永逸 - 即 function 可以轻松地将集合转换为 Z1D78DC8ED41214E50AEZ8B1 到closure2445生成密钥:

fn map_by<I,K,V>(iterable: I, f: impl Fn(&V) -> K) -> HashMap<K,V>
where I: IntoIterator<Item = V>,
      K: Eq + Hash
{
    iterable.into_iter().map(|v| (f(&v), v)).collect()
}

Allowing you to say让你说

 map_by(data_array.iter(), |item| &item.id)

Here it is in the playground:这是在操场上:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=87c0e4d1e68ccb6dd3f2c43ac9f318c7 https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=87c0e4d1e68ccb6dd3f2c43ac9f318c7

Please nudge me in the right direction if I have this wrong.如果我有这个错误,请朝正确的方向轻推我。

Is there a function like this lying around in std?是否有像这样的 function 躺在 std 中?

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

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