在 Rust 中,如何从 HashMap 的键创建 HashSet?

Mar*_*iet 8 rust

我有两个HashMaps 并且想要计算键的交集。是否有可能HashSet从任何HashMap::keys()回报中构建一个?例如:

use std::collections::{HashSet, HashMap};

fn main() {
    let mut map1: HashMap<i64, i64> = HashMap::new();
    let mut map2: HashMap<i64, i64> = HashMap::new();

    // Add some values into the HashMaps for demonstration
    map1.insert(1, 10);
    map1.insert(5, 50);
    map2.insert(3, 30);
    map2.insert(5, 50);

    let set1: HashSet<i64> = HashSet::from(map1.keys());  // How to do this?
    let set2: HashSet<i64> = HashSet::from(map2.keys());  // How to do this?

    let set3 = set1.intersection(&set2); // What I'm looking to accomplish
    // set3 should contain [5], as this is the one key shared by the two HashMaps
}
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 10

简单的解决方案

您的代码只需要进行一些调整即可实际编译(请参阅 Playground):

use std::collections::{HashSet, HashMap};

fn main() {
    let mut map1 = HashMap::new();
    let mut map2 = HashMap::new();

    // Add some values into the HashMaps for demonstration
    map1.insert(1, 10);
    map1.insert(5, 50);
    map2.insert(3, 30);
    map2.insert(5, 50);

    let set1: HashSet<i64> = map1.keys().cloned().collect();
    let set2: HashSet<i64> = map2.keys().cloned().collect();

    let set3 = set1.intersection(&set2);
    println!("{:?}", set3);
}
Run Code Online (Sandbox Code Playgroud)

特别要注意map1.keys().cloned().collect()

  • HashMap<K, V>::keys()返回一个Iterator<Item = &'a K>,
  • .cloned()将其转换为Iterator<Item = K>,
  • .collect()从中构建一个集合,因为HashSet实现了FromIterator特征。

但是,这不是很有效:

  • 复杂性明智:O(map1.size() + map2.size()).
  • 内存明智:潜在的大分配。

高效的解决方案

实施intersection直接的键HashMap


Pet*_*all 5

您只需要收集到HashSet

let set1: HashSet<i64> = map1.keys().copied().collect(); 
let set2: HashSet<i64> = map2.keys().copied().collect();
Run Code Online (Sandbox Code Playgroud)

使用copied()将取消引用键并复制它们,因为您想要一个HashSet<i64>不是HashSet<&i64>