当我将值移入其中时,如何有条件地添加或更新地图?

时间:2016-01-22 23:26:37

标签: rust

我想要更新或添加条目的BTreeMap,具体取决于是否找到密钥。我添加或更新的值可能非常大,所以我想移动它,而不是复制它。然而,无论我尝试什么,Rust的借阅检查器都让我无法做到这一点。

骨架演示程序:

use std::collections::BTreeMap;

#[derive(Debug)]
struct Thing {
    value: String
}

fn add_or_update(map: &mut BTreeMap<i32, Thing>, key: i32, value: String) {
    // ?????????????????????
    // ?? it is a mystery ??
    // ?????????????????????
}

fn main() {
    let mut container = BTreeMap::<i32, Thing>::new();

    add_or_update(&mut container, 42, "Hello!".to_string()); // add
    add_or_update(&mut container, 42, "World!".to_string()); // update

    println!("{:?}", container);
}

以下是我尝试以各种方式实施add_or_update

这显然失败了,因为map可以为整个匹配表达式可靠地借用:

match map.get_mut(&key) {
    Some(ref mut thing) => { thing.value = value; },
    None                => { map.insert(key, Thing { value: value }); },
}

这是一种借用违规行为,因为map是为整个if / else表达式借用的,而不只是&#39; if&#39;部分内容:

if let Some(ref mut thing) = map.get_mut(&key) {
    thing.value = value;
}
else {
    map.insert(key, Thing {
        value: value
    });
}

这修复了借用违规行为,但也无法正常工作,因为value现在已经移动到两个地方,Rust编译器不再认为它们是独立的:

let mut updated = false;
if let Some(ref mut thing) = map.get_mut(&key) {
    updated = true;
    thing.value = value;
}
if !updated {
    map.insert(key, Thing {
        value: value
    });
}

现在我没有想法。有没有办法做到这一点?

如果不是因为我需要移动该值而不是复制它,那么最后一个例子是可行的。

if let借用整个 if / else表达式的方式令人极为疯狂。为什么它会借用&#34;否则&#34;部分?!?只有在if let绑定失败时才会运行代码!

0 个答案:

没有答案