23

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);
    }

}

1 Answer 1

33

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);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.