有没有办法为特定的 HashSet 或 HashMap 覆盖类型的相等性和哈希函数?
Is there a way to override the equality and hash functions of a type for a particular HashSet or HashMap?
我有一个 User
结构:
struct User {
id: i32,
email: String,
// ...
}
在我的代码的一部分中,我想通过数据库 ID 获取唯一用户,但在另一段代码中,我想通过电子邮件地址获取唯一用户。我曾在系统上工作过,用户使用 LDAP CN、电子邮件等映射到外部系统帐户,并且在某些情况下能够通过不同的 ID 映射用户非常有用。
在 .NET 中,您可以传入 IEqualityComparer
interface to override equals/hash for a particular Dictionary
. In C++, the unordered_map
class 具有散列和 eq 函数的通用参数。在 Java 中,我学会了只使用 Map
s 而不是 Set
s 当我想获得键控某些东西的唯一值时,但这可能很尴尬,尤其是对于复合键。
老实说,这是一种非常罕见的情况,并且总是有使用映射而不是集合或使用自己的 Hash
/Eq
impl
块创建包装器结构的解决方法。我只是好奇在 Rust 中是否有一种我还不知道的更简单的方法来做到这一点。
使用一个或多个 newtypes 以及您想要的相等性和散列的特定定义:
use std::hash::{Hash, Hasher};
struct ById(User);
impl Hash for ById {
fn hash<H>(&self, h: &mut H)
where
H: Hasher,
{
self.0.id.hash(h)
}
}
impl PartialEq for ById {
fn eq(&self, other: &Self) -> bool {
self.0.id == other.0.id
}
}
impl Eq for ById {}
fn example(k: User, v: i32) {
let mut h = std::collections::HashMap::new();
h.insert(ById(k), v);
}
Do I need to use .0
to get at the underlying User
when I pull ById
s out of the map?
是的。
Is there any magic to implicitly convert to the underlying User
?
没有
I might be better off implementing Deref
or something.
另请参阅:
- How to use a struct's member as its own key when inserting the struct into a map without duplicating it?
我有一个 User
结构:
struct User {
id: i32,
email: String,
// ...
}
在我的代码的一部分中,我想通过数据库 ID 获取唯一用户,但在另一段代码中,我想通过电子邮件地址获取唯一用户。我曾在系统上工作过,用户使用 LDAP CN、电子邮件等映射到外部系统帐户,并且在某些情况下能够通过不同的 ID 映射用户非常有用。
在 .NET 中,您可以传入 IEqualityComparer
interface to override equals/hash for a particular Dictionary
. In C++, the unordered_map
class 具有散列和 eq 函数的通用参数。在 Java 中,我学会了只使用 Map
s 而不是 Set
s 当我想获得键控某些东西的唯一值时,但这可能很尴尬,尤其是对于复合键。
老实说,这是一种非常罕见的情况,并且总是有使用映射而不是集合或使用自己的 Hash
/Eq
impl
块创建包装器结构的解决方法。我只是好奇在 Rust 中是否有一种我还不知道的更简单的方法来做到这一点。
使用一个或多个 newtypes 以及您想要的相等性和散列的特定定义:
use std::hash::{Hash, Hasher};
struct ById(User);
impl Hash for ById {
fn hash<H>(&self, h: &mut H)
where
H: Hasher,
{
self.0.id.hash(h)
}
}
impl PartialEq for ById {
fn eq(&self, other: &Self) -> bool {
self.0.id == other.0.id
}
}
impl Eq for ById {}
fn example(k: User, v: i32) {
let mut h = std::collections::HashMap::new();
h.insert(ById(k), v);
}
Do I need to use
.0
to get at the underlyingUser
when I pullById
s out of the map?
是的。
Is there any magic to implicitly convert to the underlying
User
?
没有
I might be better off implementing
Deref
or something.
另请参阅:
- How to use a struct's member as its own key when inserting the struct into a map without duplicating it?