从地图获取值并修改相同范围内的地图[重复]

问题描述 投票:1回答:1

这是一个简单的程序,它在map中查找以前的值并将新值放入其中。它不会编译,因为第一次查找不可靠地借用mapinsert想要可变地借用map

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<i32, i32> = HashMap::new();
    map.insert(0, 0);

    (1..5).for_each(|x| {
        let prev = map.get(&(x - 1)).unwrap();
        map.insert(x, (prev + 1) * 10);
    });

    map.iter().for_each(|(k, v)| println!("{} -> {}", k, v));
}

这个问题可以通过使用clone()来获得prev来解决

let prev = map.get(&(x - 1)).unwrap().clone();

并获得输出:

0 -> 0
1 -> 10
2 -> 110
3 -> 1110
4 -> 11110

我怎么办才能不在这里使用clone()

rust
1个回答
2
投票

HashMap::get()返回Option<&V>,你打开它,得到&V,所以你最终得到prev是一个指向map内部的不可变引用。这就是为什么你有一个不可改变的借钱mapprev的类型是&i32

要解决您的问题,您可以取消引用该引用:

let prev = *map.get(&(x - 1)).unwrap();

在这种情况下,prev的类型是i32,它只是堆栈上的值。它没有指向map =>你不能不可靠地借map所以你可以在下一行可变地借map

如果您启用Rust 2018版本,因为non-lexical lifetimes support,您的原始代码可以正常工作。

请注意,HashMap未排序,因此输出行以任意顺序生成。如果您需要排序,可以考虑使用BTreeMap

如果您根本不想使用Copy(通过*)或Clone,并且不想切换到Rust 2018,则可以执行以下操作:

let value_to_insert = {
    let prev = map.get(&(x - 1)).unwrap();
    (prev + 1) * 10
}
map.insert(x, value_to_insert)

这与非词汇生命在Rust 2018中自动为你做的事情几乎相同。

© www.soinside.com 2019 - 2024. All rights reserved.