问题
I have a struct that has, among other data, a unique id
:
struct Foo {
id: u32,
other_data: u32,
}
I want to use the id
as the key and keep it inside of the struct:
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);
}
}
This works:
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);
}
Is there any way to write baz.get(1).unwrap().other_data;
instead of baz.get(&Foo { id: 1, other_data: 0 }).unwrap().other_data;
?
An alternative might be a HashMap
where the key is contained inside the struct
. However, I can't have the id
inside the struct and a duplicate id
used for the key
.
回答1:
When you check out the signature for HashSet::get, you'll note that it's slightly more complicated than you might expect:
fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
where
T: Borrow<Q>,
Q: Hash + Eq,
This is done precisely to solve your problem. get
accepts a reference to any type (&Q
) that can be borrowed from the type in the set (T: Borrow<Q>
). T
should be read as "my type" and Q
should be read as "the query type".
Thus, you need to implement Borrow for your type:
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);
}
See also:
- What's the idiomatic way to make a lookup table which uses field of the item as the key?
- How can I keep a reference to a key after it has been inserted into a HashMap?
- How to avoid temporary allocations when using complex key for HashMap?
来源:https://stackoverflow.com/questions/45384928/is-there-any-way-to-look-up-in-hashset-by-only-the-value-the-type-is-hashed-on