【问题标题】:HashSet as key for other HashSetHashSet 作为其他 HashSet 的键
【发布时间】:2016-08-02 10:12:25
【问题描述】:

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

幸运的是,我的情况更受约束,所以我需要的是:

  • HashSet<String> 类型实现hash 特征only
  • 现在散列应该很简单:

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

【问题讨论】:

    标签: hash rust hashset


    【解决方案1】:

    您的代码存在几个问题,主要是您试图通过在 newtype 包装器上调用 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)) 排序所有项目。

    【讨论】:

    • 未成年人:Vec&lt;_&gt;for s in a
    • 非常感谢 Dogbert!我会把你的答案标记为正确的。这是一个使用您的代码 play.rust-lang.org/… 的小工作示例,我将阅读有关 BTreeSet 的更多信息,看看它是否适合我的用例,非常感谢!
    • Dogbert:我已经测试了 BTreeSet,它们正是我正在寻找的。因为我处理的集合需要在我的代码的某些部分中排序,所以它们很自然。此外,我不需要实现 Hash 特征,它可以让事情变得更容易。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2011-08-20
    • 2018-07-06
    • 2015-03-05
    • 2012-09-24
    相关资源
    最近更新 更多