作者:沉佩颖岳玲 | 来源:互联网 | 2023-01-27 17:39
我有一个结构,除其他数据外,还有一个唯一的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(&self, state: &mut H) {
self.id.hash(state);
}
}
这有效:
pub fn bar() {
let mut baz: HashSet = 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
.
1> Shepmaster..:
当您签出签名时HashSet::get
,您会注意到它比您预期的要复杂一些:
fn get(&self, value: &Q) -> Option<&T>
where
T: Borrow,
Q: Hash + Eq,
这样做恰好可以解决您的问题.get
接受对&Q
可以从set(T: Borrow
)中的类型借用的任何类型()的引用.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(&self, state: &mut H) {
self.id.hash(state);
}
}
impl Borrow 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使用复杂键时如何避免临时分配?