我有一个 User
结构:
struct User {
id: i32,
email: String,
// ...
}
在我的代码的一部分中,我想通过数据库 ID 获取唯一用户,但在另一段代码中,我想通过电子邮件地址获取唯一用户。我曾在系统上工作过,用户使用 LDAP CN、电子邮件等映射到外部系统帐户,并且在某些情况下能够通过不同的 ID 映射用户非常有用。
在 .NET 中,您可以传入一个 IEqualityComparer
。为特定的 Dictionary
覆盖 equals/hash 的接口(interface)。在 C++ 中,unordered_map
类具有散列和 eq 函数的通用参数。在 Java 中,当我想获得唯一值时,我学会了只使用 Map
而不是 Set
,但这可能很尴尬,尤其是对于复合键。
老实说,这是一种非常罕见的情况,总有使用映射而不是集合或使用自己的 Hash
/Eq
创建包装器结构的解决方法impl
block 。我只是好奇在 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.
Is it considered a bad practice to implement Deref for newtypes?
另见:
- How to implement Eq and Hash for my own structs to use them as a HashMap key?
- How to use a struct's member as its own key when inserting the struct into a map without duplicating it?
- How can I use a custom hash function in a HashSet or HashMap?
- Are there any HashMap implementations with consistent ordering between program runs?
关于rust - 有没有办法为特定的 HashSet 或 HashMap 覆盖类型的相等性和哈希函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65671746/