Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rust, how do I create a HashSet from the keys of a HashMap?

Tags:

rust

I have two HashMaps and want to compute the intersection of the keys. Is it possible to construct a HashSet out of whatever HashMap::keys() returns? For example:

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
}
like image 251
Marijn van Vliet Avatar asked Dec 03 '19 11:12

Marijn van Vliet


People also ask

Can I use HashSet as key for HashMap?

Hashmap internally do not implements hashset or any set for its implementation. Hashset internally uses Hashmap for its implementation. HashMap Stores elements in form of key-value pair i.e each element has its corresponding key which is required for its retrieval during iteration.

How do Hashmaps work rust?

Hashmap in rust is a structure which comprises of the look-up table and data in it in form of key and value pair which will be used for storing and retrieving data continuously. Hashmap needs to be explicitly imported from the rust inbuilt library collection before that can be used within the program.

What is a HashSet rust?

A HashSet in Rust is a collection that holds a unique value inside it and does not permit the entry of any duplicate values. HashSet is different from HashMap in the sense, that in HashSet, there is no key-value pair and the value or the data inside it, should be directly accessed.

What is the difference between HashMap and HashSet in rust?

HashSet is different from HashMap in the sense, that in HashSet, there is no key-value pair and the value or the data inside it, should be directly accessed. The HashSet structure is defined inside the std::collections of the Rust.

How do I implement a HashSet?

A hash set implemented as a HashMap where the value is (). As with the HashMap type, a HashSet requires that the elements implement the Eq and Hash traits. This can frequently be achieved by using # [derive (PartialEq, Eq, Hash)]. If you implement these yourself, it is important that the following property holds:

What happens when you create an empty HashSet in Java?

Creates an empty HashSet. The hash set is initially created with a capacity of 0, so it will not allocate until it is first inserted into. Creates an empty HashSet with at least the specified capacity. The hash set will be able to hold at least capacity elements without reallocating.

How do I check if an element is present in HashSet?

The function contains () is used to check whether an element is present in the HashSet. This function contains (), will directly pass the control to execute a statement or a block of a statement, if an element is found in the HashMap.


2 Answers

You just need to collect into the HashSet:

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

Using copied() will dereference the keys and copy them, since you want a HashSet<i64> not a HashSet<&i64>

like image 109
Peter Hall Avatar answered Oct 11 '22 06:10

Peter Hall


The simple solution

Your code only needs a few tweaks to actually compile (see 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);
}

In particular, note map1.keys().cloned().collect():

  • HashMap<K, V>::keys() returns an Iterator<Item = &'a K>,
  • .cloned() transforms that to an Iterator<Item = K>,
  • .collect() builds a collection from that, since HashSet implements the FromIterator trait.

However, this is not very efficient:

  • Complexity wise: O(map1.size() + map2.size()).
  • Memory wise: potentially large allocations.

The efficient solution

Implement intersection directly on the keys of HashMap.

like image 23
Matthieu M. Avatar answered Oct 11 '22 06:10

Matthieu M.