Rust 尝试实现查找或插入时出现HashMap借用问题

Rust 尝试实现查找或插入时出现HashMap借用问题,rust,Rust,我尝试实现自己类似的find\u或\u insert方法,如下所示: use std::collections::HashMap; pub struct SomeManager { next: i32, types: HashMap<i32, i32>, } impl SomeManager { pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 { m

我尝试实现自己类似的
find\u或\u insert
方法,如下所示:

use std::collections::HashMap;

pub struct SomeManager {
    next: i32,
    types: HashMap<i32, i32>,
}

impl SomeManager {
    pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
        match self.types.get(&k) {
            Some(ref x) => return *x,
            None => {
                self.types.insert(k, self.next);
                self.next += 1;
                return self.types.get(&k).unwrap();
            }
        }
    }
}

fn main() {}
我知道有一些标准的方法可以实现这个功能,但是我希望这个方法尽可能的简单——它会被频繁调用,而且几乎所有的时候这些值都已经存在了

据我所知,当我们调用
self.types.get
时,我们将其借用到match语句的范围内,因此我们不能调用
self.types.insert
。我尝试将方法从None分支移出match语句,但也失败了

我找到的唯一有效解决方案需要调用
get
两次:

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let is_none = match self.types.get(&k) {
        Some(ref x) => false,
        None => true,
    };
    if is_none {
        self.types.insert(k, self.next);
        self.next += 1;
    }
    self.types.get(&k).unwrap()
}
pub fn get_type&'a i32{
let is_none=匹配self.types.get(&k){
一些(参考x)=>错误,
无=>正确,
};
如果没有{
self.types.insert(k,self.next);
self.next+=1;
}
self.types.get(&k).unwrap()
}

如何解决这种情况?

HashMap上有几种方法可以实现这些复杂情况。最值得注意的是,对于您的情况,以及:


请注意,在第一种情况下,当键存在于映射中时,将执行一次查找,当键不存在时,将执行三次查找。您的最后一次尝试在任何一种情况下都会进行两次查找。这是后者的美化版本:

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let contains = self.types.contains_key(&k);
    if !contains {
        self.types.insert(k, self.next);
        self.next += 1;
    }
    self.types.get(&k).unwrap()
}
pub fn get_type&'a i32{
let contains=self.types.contains_键(&k);
如果!包含{
self.types.insert(k,self.next);
self.next+=1;
}
self.types.get(&k).unwrap()
}
我认为,由于借用限制,如果没有map实现的支持,就不可能避免第二次查找


在任何情况下,使用都优于上述方法(例如,它可能更有效,实际上需要更少的查找),因此我建议坚持使用它。

@Vladimitaveveveveve:注意!我不知道将类似于
&mut self.path
的东西传递给一个将
self
作为接收器的方法是可能的。这真是太棒了。@Vladimitaveveveveve:它不需要
self
,至少与
self.path
中的
self
不一样;它采用了
self.types
,使借用不相交。对于那些仍然遇到这种情况的人来说,这些方法似乎已经不存在了,而实现这一点的新方法是使用.entry()API,如下所述:第二种解决方案对我来说非常理想,但它也无法编译-出于某种原因,它说以前的借用(在比赛中)在比赛结束时结束function@Mikhail,请检查此项。返回引用意味着
v
的生存期是
'a
,因此
自我类型
借用的生存期是
'a
——您在其周围放的花括号根本没有帮助。
pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let next = &mut self.next;

    self.types.entry(k).or_insert_with(|| {
        let value = *next;
        *next += 1;
        value
    })
}
pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let contains = self.types.contains_key(&k);
    if !contains {
        self.types.insert(k, self.next);
        self.next += 1;
    }
    self.types.get(&k).unwrap()
}