有什么方法可以仅通过类型哈希值来查找 HashSet 吗?

2023-11-22

我有一个结构体,除其他数据外,还有一个独特的id:

struct Foo {
    id: u32,
    other_data: u32,
}

我想使用id作为键并将其保留在结构内部:

use std::collections::HashSet;
use std::hash::{Hash, Hasher};
impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        self.id == other.id
    }
}
impl Eq for Foo {}
impl Hash for Foo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

这有效:

pub fn bar() {
    let mut baz: HashSet<Foo> = HashSet::new();
    baz.insert(Foo {
        id: 1,
        other_data: 2,
    });
    let other_data = baz.get(&Foo {
        id: 1,
        other_data: 0,
    }).unwrap()
        .other_data;
    println!("other_data: {}", other_data);
}

有什么办法可以写baz.get(1).unwrap().other_data;代替baz.get(&Foo { id: 1, other_data: 0 }).unwrap().other_data;?

另一种选择可能是HashMap其中密钥包含在struct。然而,我不能拥有id结构内部和重复的id用于key.


当您检查签名时HashSet::get,您会注意到它比您预期的稍微复杂一些:

fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T> 
where
    T: Borrow<Q>,
    Q: Hash + Eq, 

这个做完了正是为了解决您的问题. get接受对任何类型的引用(&Q) 可以从集合 (T: Borrow<Q>). T应该读作“我的类型”并且Q应理解为“查询类型”。

因此,您需要实施Borrow适合您的类型:

use std::borrow::Borrow;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

type Id = u32;

#[derive(Debug, Eq)]
struct Foo {
    id: Id,
    other_data: u32,
}

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        self.id == other.id
    }
}

impl Hash for Foo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

impl Borrow<Id> for Foo {
    fn borrow(&self) -> &Id {
        &self.id
    }
}

fn main() {
    let mut baz = HashSet::new();
    baz.insert(Foo {
        id: 1,
        other_data: 2,
    });

    let other_data = baz.get(&1).unwrap().other_data;
    println!("other_data: {}", other_data);
}

也可以看看:

  • 制作使用项目字段作为键的查找表的惯用方法是什么?
  • 在将键插入 HashMap 后,如何保留对键的引用?
  • HashMap 使用复杂键时如何避免临时分配?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有什么方法可以仅通过类型哈希值来查找 HashSet 吗? 的相关文章

随机推荐