根据同一个 Hashmap 中的另一个值插入到一个 HashMap 中
Insert into a HashMap based on another value in the same Hashmap
我正在尝试根据同一 HashMap 中的另一个值将一个值插入到 HashMap 中,如下所示:
use std::collections::HashMap;
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", 1);
let some_val = some_map.get("a").unwrap();
if *some_val != 2 {
some_map.insert("b", *some_val);
}
}
发出此警告:
warning: cannot borrow `some_map` as mutable because it is also borrowed as immutable
--> src/main.rs:10:9
|
7 | let some_val = some_map.get("a").unwrap();
| -------- immutable borrow occurs here
...
10 | some_map.insert("b", *some_val);
| ^^^^^^^^ --------- immutable borrow later used here
| |
| mutable borrow occurs here
|
= note: `#[warn(mutable_borrow_reservation_conflict)]` on by default
= warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
= note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
如果我改为尝试 更新 现有值,我可以使用内部突变和 RefCell,如 所述。
如果我尝试插入 或 更新基于 自身 的值,我可以使用条目 API,如所述 .
我可以通过克隆来解决这个问题,但我宁愿避免这种情况,因为在我的实际代码中检索到的值有些复杂。这需要不安全的代码吗?
编辑
由于之前的答案完全是错误的,根本没有回答问题,所以有代码没有显示任何警告 (playground)
现在它是一个具有 Rc<_>
个值的散列图,val_rc
仅包含实际数据的引用计数器(在本例中为 1
)。因为它只是一个计数器,所以没有克隆它的成本。但是请注意,只有一个数字副本存在,因此如果您修改 some_map["a"]
的值,那么 some_map["b"]
也会被修改,因为它们指的是一块内存。另请注意,1
存在于堆栈中,因此如果您打算添加许多重对象,最好考虑将其转换为 Rc<Box<_>>
。
use std::collections::HashMap;
use std::rc::Rc;
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", Rc::new(1));
let val_rc = Rc::clone(some_map.get("a").unwrap());
if *val_rc != 2 {
some_map.insert("b", val_rc);
}
}
上一个答案
很难说出你到底在找什么,但在这种特殊情况下,如果你只需要检查值,那么在更新 hashmap 之前销毁借用的值。一个又脏又丑的代码会是这样的:
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", 1);
let is_ok = false;
{
let some_val = some_map.get("a").unwrap();
is_ok = *some_val != 2;
}
if is_ok {
some_map.insert("b", *some_val);
}
}
我正在尝试根据同一 HashMap 中的另一个值将一个值插入到 HashMap 中,如下所示:
use std::collections::HashMap;
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", 1);
let some_val = some_map.get("a").unwrap();
if *some_val != 2 {
some_map.insert("b", *some_val);
}
}
发出此警告:
warning: cannot borrow `some_map` as mutable because it is also borrowed as immutable
--> src/main.rs:10:9
|
7 | let some_val = some_map.get("a").unwrap();
| -------- immutable borrow occurs here
...
10 | some_map.insert("b", *some_val);
| ^^^^^^^^ --------- immutable borrow later used here
| |
| mutable borrow occurs here
|
= note: `#[warn(mutable_borrow_reservation_conflict)]` on by default
= warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
= note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
如果我改为尝试 更新 现有值,我可以使用内部突变和 RefCell,如
如果我尝试插入 或 更新基于 自身 的值,我可以使用条目 API,如所述
我可以通过克隆来解决这个问题,但我宁愿避免这种情况,因为在我的实际代码中检索到的值有些复杂。这需要不安全的代码吗?
编辑 由于之前的答案完全是错误的,根本没有回答问题,所以有代码没有显示任何警告 (playground)
现在它是一个具有 Rc<_>
个值的散列图,val_rc
仅包含实际数据的引用计数器(在本例中为 1
)。因为它只是一个计数器,所以没有克隆它的成本。但是请注意,只有一个数字副本存在,因此如果您修改 some_map["a"]
的值,那么 some_map["b"]
也会被修改,因为它们指的是一块内存。另请注意,1
存在于堆栈中,因此如果您打算添加许多重对象,最好考虑将其转换为 Rc<Box<_>>
。
use std::collections::HashMap;
use std::rc::Rc;
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", Rc::new(1));
let val_rc = Rc::clone(some_map.get("a").unwrap());
if *val_rc != 2 {
some_map.insert("b", val_rc);
}
}
上一个答案
很难说出你到底在找什么,但在这种特殊情况下,如果你只需要检查值,那么在更新 hashmap 之前销毁借用的值。一个又脏又丑的代码会是这样的:
fn main() {
let mut some_map = HashMap::new();
some_map.insert("a", 1);
let is_ok = false;
{
let some_val = some_map.get("a").unwrap();
is_ok = *some_val != 2;
}
if is_ok {
some_map.insert("b", *some_val);
}
}