HashSet 作为其他 HashSet 的键
HashSet as key for other HashSet
我正在尝试使用 HashSet<String>
作为其他 HashSet
的密钥。
我发现 指出要为 HashSet<String>
实现 Hash
特性,但我无法使我的具体案例起作用。
幸好我的case比较有约束力,所以我需要的是:
- 为类型
HashSet<String>
实现hash
特征仅
- 散列现在应该非常简单:
集合 {"q3", "q1", "q2"}
应该被散列为一个简单的有序的、连接的字符串版本,类似于 hash("q1-q2-q3")
。获得 "q1-q2-q3"
不是问题,但在 hash
中使用它会引发各种我无法处理的错误。
这是我的实现尝试,但是没有用。我认为 StateSet
包装器不是正确的做法,因为我丢失了所有重要的 HashSet
方法
use std::collections::{HashMap,HashSet};
use std::hash::{Hash,Hasher};
type State = String;
struct StateSet(HashSet<State>);
impl PartialEq for StateSet {
fn eq(&self, other: &StateSet) -> bool {
self.is_subset(&other) && other.is_subset(&self)
}
}
impl Eq for StateSet {}
impl Hash for StateSet {
fn hash<H>(&self, state: &mut H) where H: Hasher {
let a: Vec<State> = self.iter().collect();
a.sort();
for s in a.iter() {
s.hash(state);
}
}
}
fn main() {
let hmap: HashSet<StateSet> = HashSet::new();
}
您的代码有几个问题,主要问题是您试图通过在新类型包装器上调用它们来访问 HashSet
上的方法。您需要通过将 self
替换为 self.0
直接在 HashSet
上调用它们。这是最终的工作代码:
use std::collections::{HashMap,HashSet};
use std::hash::{Hash,Hasher};
type State = String;
struct StateSet(HashSet<State>);
impl PartialEq for StateSet {
fn eq(&self, other: &StateSet) -> bool {
self.0.is_subset(&other.0) && other.0.is_subset(&self.0)
}
}
impl Eq for StateSet {}
impl Hash for StateSet {
fn hash<H>(&self, state: &mut H) where H: Hasher {
let mut a: Vec<&State> = self.0.iter().collect();
a.sort();
for s in a.iter() {
s.hash(state);
}
}
}
fn main() {
let hmap: HashSet<StateSet> = HashSet::new();
}
此外,我强烈建议您在此处使用 BTreeSet
,它实现了 Hash
,因为它按排序顺序存储元素。它的 Hash
实施绝对应该比您的实施更快,后者对所有项目进行 O(n log(n))
排序。
我正在尝试使用 HashSet<String>
作为其他 HashSet
的密钥。
我发现 HashSet<String>
实现 Hash
特性,但我无法使我的具体案例起作用。
幸好我的case比较有约束力,所以我需要的是:
- 为类型
HashSet<String>
实现 - 散列现在应该非常简单:
hash
特征仅
集合 {"q3", "q1", "q2"}
应该被散列为一个简单的有序的、连接的字符串版本,类似于 hash("q1-q2-q3")
。获得 "q1-q2-q3"
不是问题,但在 hash
中使用它会引发各种我无法处理的错误。
这是我的实现尝试,但是没有用。我认为 StateSet
包装器不是正确的做法,因为我丢失了所有重要的 HashSet
方法
use std::collections::{HashMap,HashSet};
use std::hash::{Hash,Hasher};
type State = String;
struct StateSet(HashSet<State>);
impl PartialEq for StateSet {
fn eq(&self, other: &StateSet) -> bool {
self.is_subset(&other) && other.is_subset(&self)
}
}
impl Eq for StateSet {}
impl Hash for StateSet {
fn hash<H>(&self, state: &mut H) where H: Hasher {
let a: Vec<State> = self.iter().collect();
a.sort();
for s in a.iter() {
s.hash(state);
}
}
}
fn main() {
let hmap: HashSet<StateSet> = HashSet::new();
}
您的代码有几个问题,主要问题是您试图通过在新类型包装器上调用它们来访问 HashSet
上的方法。您需要通过将 self
替换为 self.0
直接在 HashSet
上调用它们。这是最终的工作代码:
use std::collections::{HashMap,HashSet};
use std::hash::{Hash,Hasher};
type State = String;
struct StateSet(HashSet<State>);
impl PartialEq for StateSet {
fn eq(&self, other: &StateSet) -> bool {
self.0.is_subset(&other.0) && other.0.is_subset(&self.0)
}
}
impl Eq for StateSet {}
impl Hash for StateSet {
fn hash<H>(&self, state: &mut H) where H: Hasher {
let mut a: Vec<&State> = self.0.iter().collect();
a.sort();
for s in a.iter() {
s.hash(state);
}
}
}
fn main() {
let hmap: HashSet<StateSet> = HashSet::new();
}
此外,我强烈建议您在此处使用 BTreeSet
,它实现了 Hash
,因为它按排序顺序存储元素。它的 Hash
实施绝对应该比您的实施更快,后者对所有项目进行 O(n log(n))
排序。