How can I get a reference to the key and value immediately after inserting into a `HashMap`?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 } } } |
我想在将密钥插入
TL; DR:您不能(现在?)
编译器会告诉您为什么它不起作用。不要犹豫,阅读Rust编译器消息;它们并不可怕,已经付出了很多努力!
1 2 3 4 5 6 7 8 9 | 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代码。
1 | fn insert(self, value: V) -> &'a mut V |
关于该错误消息的其他问题/答案对有100多个,因此,我假设您已经阅读了足够多的问题/答案,以了解问题所在;这就是为什么我们毕竟要回答有关堆栈溢出的问题!
那么为什么会这样呢?这很难回答。当您插入
如果缺少该值,然后您插入一个值,则密钥将从条目中移出并进入
但是,考虑得更深一点,在插入值之后,从
另请参见将密钥插入HashMap后如何保留对其的引用?
我很确定在这种情况下您不需要该功能。
如果要为新值调用它,只需在插入之前完成所有这些操作:
1 2 | hook(&k, &v); a.insert(k, v); |
如果您只想对旧值执行此操作,而在以前没有值时不执行任何操作,则可以:
1 2 3 4 5 | Occupied(mut occupied) => { let old = occupied.insert(v); hook(occupied.key(), &old); Some(old) } |
如果要使用旧值调用钩子(如果有的话),而用新值插入(似乎不一致),则可以在添加之前调用它,由于参数只是引用,因此
1 2 3 4 5 | Vacant(vacant) => { hook(vacant.key(), &v); let v = vacant.insert(v); None } |