HashSet 作为其他 HashSet 的键

HashSet as key for other HashSet

我正在尝试使用 HashSet<String> 作为其他 HashSet 的密钥。 我发现 指出要为 HashSet<String> 实现 Hash 特性,但我无法使我的具体案例起作用。

幸好我的case比较有约束力,所以我需要的是:

集合 {"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(); 
}

(playground)

您的代码有几个问题,主要问题是您试图通过在新类型包装器上调用它们来访问 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)) 排序。