插入`HashMap`后如何立即获得对键和值的引用? [英] How can I get a reference to the key and value immediately after inserting into a `HashMap`?

查看:42
本文介绍了插入`HashMap`后如何立即获得对键和值的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

use std::collections::HashMap;
use std::collections::hash_map::Entry::*;

fn hook(k: &str, v: &str) {}

fn tt(k: String, v: String) -> Option<String> {
    let mut a: HashMap<String, String> = HashMap::new();
    match a.entry(k) {
        Occupied(mut occupied) => {
            let old = occupied.insert(v);
            //hook(&k, &old);
            Some(old)
        }
        Vacant(vacant) => {
            let v = vacant.insert(v);
            let k = vacant.key(); // Why doesn't it work?
            //hook(&k, v);
            None
        }
    }
}

我想在将键插入 HashMap 后立即调用 hook.看来我必须使用Entry.但是,我无法在 vacant.insert 之后立即调用 vacant.key().

I would like to call hook immediately after a key is inserted into the HashMap. It seems I have to use Entry. However, I am unable to call vacant.key() right after vacant.insert.

推荐答案

TL;DR:你不能(现在?)

TL;DR: You cannot (right now?)

编译器告诉你为什么它不起作用.不要犹豫,阅读 Rust 编译器消息;他们并不可怕,而且他们已经付出了很多努力!

The compiler tells you why it doesn't work. Don't hesitate to read Rust compiler messages; they aren't scary and a lot of effort has gone into them!

error[E0382]: use of moved value: `vacant`
  --> src/main.rs:16:21
   |
15 |             let v = vacant.insert(v);
   |                     ------ value moved here
16 |             let k = vacant.key();
   |                     ^^^^^^ value used here after move
   |
   = note: move occurs because `vacant` has type `std::collections::hash_map::VacantEntry<'_, std::string::String, std::string::String>`, which does not implement the `Copy` trait

这只是普通的 Rust 代码.VacantEntry::insert 按值消耗self,返回对插入值的引用:

This is just normal Rust code. VacantEntry::insert consumes selfby value, returning a reference to the inserted value:

fn insert(self, value: V) -> &'a mut V

超过 100 个其他问题/答案对 询问这个错误信息,所以我假设你已经阅读了足够多的内容来理解问题;这就是我们为什么要回答 Stack Overflow 上的问题!

There are over 100 other question/answer pairs that ask about this error message, so I'll assume you've read enough of them to understand the problem; that's why we answer questions on Stack Overflow after all!

那么为什么会这样?这更难回答.当您插入 HashMap 时,它会获得键和值的所有权.当您使用 entry API 时,有一个中间步骤 - 您已授予条目密钥的所有权.条目有一个对HashMap的可变引用;值所在位置的书签".

So why is it this way? That's tougher to answer. When you insert into a HashMap, it takes ownership of the key and the value. When you use the entry API, there's an intermediate step - you've given ownership of the key to the entry. The entry also has a mutable reference to the HashMap; a "bookmark" of where the value is.

当值缺失时,您插入一个值,键从条目中转移到HashMap.这意味着对条目内键的引用将无效.这就是为什么你不能对这两行重新排序.

When the value is missing and then you insert a value, the key is transferred out of the entry and into the HashMap. This means that the reference to the key inside the entry would be invalidated. That's why you can't reorder the two lines.

然而,再深入思考一下,insert返回的value指的是底层的HashMap,在插入值之后.我看不出有任何原因阻止添加返回键和值引用的函数.但是,现在不存在这样的功能.

However, thinking about it a bit deeper, the value returned from insert refers to the underlying HashMap, after the value has been inserted. I can't see any reason preventing a function from being added that returns a reference to the key and the value. However, such a function doesn't exist now.

另请参阅如何在将键插入到 HashMap 后保留对键的引用?

我很确定在这种情况下您不需要该功能.

I'm pretty sure in this case you don't need the functionality though.

如果您想为 new 值调用它,只需在插入之前执行所有这些操作:

If you want to call it for the new value, just do all of this before the insertion:

hook(&k, &v);
a.insert(k, v);

如果您只想对旧值执行此操作,而在以前没有值时什么都不做,您可以:

If you want to do it only for the old value, doing nothing when there wasn't previously a value, you can:

Occupied(mut occupied) => {
    let old = occupied.insert(v);
    hook(occupied.key(), &old);
    Some(old)
}

如果您想使用 old 值(如果有)和 new 值(如果插入)调用钩子(这似乎不一致),您可以调用它添加之前,hook 函数不会更明智,因为参数只是引用:

If you want to call the hook with the old value if there was one and the new value if inserting (which seems inconsistent), you can call it before adding, the hook function will be none the wiser as the arguments are just references:

Vacant(vacant) => {
    hook(vacant.key(), &v);
    let v = vacant.insert(v);
    None
}

这篇关于插入`HashMap`后如何立即获得对键和值的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆