Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort HashMap data by keys

Tags:

rust

Cross referencing to Rust forum, I'm generating a HashMap as in this playground / below code. How can I sort the generated result map based on the keys, in my case based on Dimension, Location:

use std::collections::HashMap;

#[derive(Debug, Eq, PartialEq, Hash, Clone)]
struct Dimension {
    item: String,
    color: String,
    size: String,
    part_number: String
}

#[derive(Debug)]
struct Delivery {
    variant: Dimension,
    location: String,
    quantity: i32,
}

pub fn main() {
    let data = vec![
        Delivery {
            variant: Dimension {item: String::from("A"),
                                color: String::from("B"),
                                size: String::from("C"),
                                part_number: String::from("D")},
            location: String::from("L"),
            quantity: 10,
        },
        Delivery {
            variant: Dimension {item: String::from("A"),
                                color: String::from("B"),
                                size: String::from("C"),
                                part_number: String::from("D")},
            location: String::from("L2"),
            quantity: 3,
        },        
        Delivery {
            variant: Dimension {item: String::from("A"),
                                color: String::from("B"),
                                size: String::from("C"),
                                part_number: String::from("D1")},
            location: String::from("L"),
            quantity: 5,
        }, 
        Delivery {
            variant: Dimension {item: String::from("A"),
                                color: String::from("B"),
                                size: String::from("C"),
                                part_number: String::from("D")},
            location: String::from("L"),
            quantity: 5,
        },        
    ];

    // The keys of this map will be groups
    let mut map: HashMap<(Dimension, String), Delivery> = HashMap::new();
    for d in data {
        let record = map
            .entry((d.variant.clone(), d.location.clone()))
            .or_insert(Delivery {
                variant: d.variant.clone(),
                location: d.location.clone(),
                quantity: 0,
            });
        record.quantity += d.quantity;
    }

    for (variant, delivery) in &map {
        println!("{:?} has {:?}", variant, delivery.quantity);
    }

}
like image 246
Hasan A Yousef Avatar asked Jan 18 '20 09:01

Hasan A Yousef


People also ask

Can we sort HashMap by key?

Java HashMap does not preserve any order by default. If there is a need to sort HashMap we sort it explicitly based on the requirements. Java provides an option to sort HashMap based on keys and values.

How do you sort HashMap keys based on values?

Our task is to sort the hashmap according to values i.e. according to marks. Solution: The idea is to store the entry set in a list and sort the list on the basis of values. Then fetch values and keys from the list and put them in a new hashmap. Thus, a new hashmap is sorted according to values.

How do you sort the values of a HashMap?

To sort the String values in the list we use a comparator. This comparator sorts the list of values alphabetically. Once, we have sorted the list, we build the HashMap based on this sorted list. HashMap entries are sorted according to String value.


1 Answers

The itertools crate extends the standard iterator so that it can be sorted:

use std::collections::HashMap;
use itertools::Itertools;  // itertools = "0.8"

#[derive(Debug, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
struct Dimension {
    item: String,
    color: String,
    size: String,
    part_number: String,
}

fn main() {
    // ...

    for key in map.keys().sorted() {
        println!("{:?} has {:?}", key, map[key].quantity);
    }
}

Alternatively, you can use BTreeMap, which is a sorted map by itself:

use std::collections::BTreeMap;

#[derive(Debug, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
struct Dimension {
    item: String,
    color: String,
    size: String,
    part_number: String
}

fn main() {
    // ...

    let mut map = BTreeMap::new();
    for d in data {
        let record = map
            .entry((d.variant.clone(), d.location.clone()))
            .or_insert(Delivery {
                variant: d.variant.clone(),
                location: d.location.clone(),
                quantity: 0,
            });
        record.quantity += d.quantity;
    }

    for (variant, delivery) in &map {
        println!("{:?} has {:?}", variant, delivery.quantity);
    }
}
like image 138
edwardw Avatar answered Oct 19 '22 07:10

edwardw