HashSet作为其他HashSet的键

时间:2016-04-12 02:07:48

标签: hash rust hashset

我尝试使用HashSet<String>作为其他HashSet的密钥。 我发现this question and answer指出要为Hash实施HashSet<String>特征,但我无法让我的具体案例发挥作用。

幸运的是,我的情况更加严格,所以我需要的是:

  • 为类型hash
  • 实施HashSet<String>特征
  • 哈希现在应该非常简单:

集合{"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

1 个答案:

答案 0 :(得分:3)

您的代码存在一些问题,主要是您尝试通过在新类型包装器上调用它们来访问HashSet上的方法。您需要使用HashSet替换self,直接在self.0上调用它们。这是最终的工作代码:

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))种所有项目的实现更快。