Closer Scrutiny of Rust Collections [Part-3]

Reading Time: 4 minutes

The Collections are the general-purpose programming data structures provided by Rust’s Standard library. Rust can provide many cool implementations of data structures like Vector, Linked list, Hash map, HashSet, and BTreeSet, etc.

This image has an empty alt attribute; its file name is rust-2-wal.png

Hello, folks!  your wait is over, here is the third blog of Closer Scrutiny of Rust Collections. I hope you have learned a lot from the first and second blog. It’s better to go with the previous blogs first to gain more understanding about Collections.
We have categorised the Rust collections into three groups:

  • Sequences.
  • Map.
  • Sets.

As we already discussed Sequences and Maps category in our previous blogs, so now let’s focus on the next topic Sets.

HashSet:

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/data inside it can be directly accessed.
The new value will override the old value if you insert a value that is already present in the HashSet.

Let’s understand more with the help of an example:

use std::collections::HashSet;

fn main() {
    // Initialise the HashSet
    let mut languages = HashSet::new();
    
    // Insert some values to the HashSet
    languages.insert("Rust");
    languages.insert("Scala");
    languages.insert("Python");
    
    // Print the size of HashSet
    println!("Size of HashSet: {}", languages.len());
    
    // Contains operation
    if languages.contains("Rust") {
        println!("Rust is present in HashSet.");
    }
    
    // Remove a Element from HashSet
    languages.remove("Python");
    
    // Print all the values from the HashMap
    for language in &languages {
        println!("{}", language);
    }
    
    // Fetch the value from the HashSet
    match languages.get( & "Rust") {
        Some(data) => {
            println!("The {} element is found.", data);
        }
        None => {
            println!("Not Present");
        }
    }
}

Output:

This image has an empty alt attribute; its file name is screenshot-from-2019-11-23-22-43-24.png

In this example, we have initialised the HashSet and inserted some values to the HashSet. Then printed the size of HashSet and checked whether the given value is present in the HashSet or not. 
After that, we have removed an element from the HashSet and printed all the value of HashSet. At last, we have fetched value from the HashSet.

In Above example we have seen various functions of HashSet to operate the HashSet like insert(), contains(), len(), remove(), get(), etc.

Now we can see some more cool operations of HashSet:

  • Union: Get all the unique elements in both sets.
  • Difference: Get all the elements that are in the first set but not the second.
  • Intersection: Get all the elements that are only in both sets.
  • Symmetric difference: Get all the elements that are in one set or the other, but not both.

Let’s understand these operations with the help of an example:

use std::collections::HashSet;

fn main() {
    // Initialise the HashSets
    let first_set: HashSet<i32> = vec![10, 20, 30].into_iter().collect();
    let second_set: HashSet<i32> = vec![30, 40, 50].into_iter().collect();

    println!("Elements in first set: {:?}", first_set);
    println!("Elements in second set: {:?}\n", second_set);

    // Print the union elements of the sets
    println!("Union of sets: {:?}", first_set.union(&second_set).collect::<Vec<&i32>>());

    // Print the difference elements of the sets
    println!("Difference of sets: {:?}", first_set.difference(&second_set).collect::<Vec<&i32>>());

    // Print the intersection elements of the sets
    println!("Intersection of sets: {:?}", first_set.intersection(&second_set).collect::<Vec<&i32>>());

    // Print the symmetric difference elements of the sets
    println!("Symmetric Difference of sets: {:?}",
             first_set.symmetric_difference(&second_set).collect::<Vec<&i32>>());
}

Output:

This image has an empty alt attribute; its file name is screenshot-from-2019-11-23-23-18-27.png

BTreeSet:

BTreeSet is the set based on B-Tree. In previous blog we have discussed in detail about the performance benefits of B-Tree.
BTreeSet is a logic error for an item to be modified in such a way that the item’s ordering relative to any other item, as determined by the Ord trait, changes while it is in the set. This is normally only possible through Cell, Refcell, global state, I/O, or unsafe code.

Let’s understand more with the help of an example:

use std::collections::BTreeSet;

fn main() {
    // Initialise the BTreeSet
    let mut first_set = BTreeSet::new();
    first_set.insert(10);
    first_set.insert(20);
    first_set.insert(30);
    
    let mut second_set = BTreeSet::new();
    second_set.insert(30);
    second_set.insert(40);
    second_set.insert(50);
    
    // Disjoint of two BTreeSets
    println!("{}", first_set.is_disjoint(&second_set));
    
    // Interection of two BTreeSets
    let intersection: Vec<_> = first_set.intersection(&second_set).cloned().collect();
    println!("{:?}", intersection);
    
    // Difference of two BTreeSets
    let diff: Vec<_> = first_set.difference(&second_set).cloned().collect();
    println!("{:?}", diff);
    
    // Symmetric difference of two BTreeSets
    let sym_diff: Vec<_> = first_set.symmetric_difference(&second_set).cloned().collect();
    println!("{:?}", sym_diff);
    
    // Union of two BTreeSets
    let union: Vec<_> = first_set.union(&second_set).cloned().collect();
    println!("{:?}", union);
}

Output:

This image has an empty alt attribute; its file name is screenshot-195.png

In this example, we have initialised two BTreeSet and insert some values in that BTreeSets. Then we have performed some operations like disjoint, intersection, difference, symmetric difference, and union.

Note: This is the final part of blogs on Collections in Rust, I hope you have learned a lot from it. I’ll post more blogs on Rust. Stay Tuned.

Happy learning!!!

This image has an empty alt attribute; its file name is footer-2.jpg

Written by 

Pankaj Chaudhary is a Software Consultant at Knoldus LLP. He has 1.5+ years of experience with good knowledge of Rust, Python, Java, and C. Now he is working as Rust developer and also works on machine learning and data analysis because he loves to play with data and extract some useful information from it. His hobbies are bike riding and explore new places.

1 thought on “Closer Scrutiny of Rust Collections [Part-3]5 min read

  1. Consider phrasing “BTreeSet is a logic error for an item to be modified in such a way that the item’s ordering relative to any other item, as determined by the Ord trait, changes while it is in the set.” as “In BTreeSet, it is a logic….” for clarity.

Comments are closed.

%d bloggers like this: