Sort HashMap data by keys

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

HashMap elements' order is not specified, as we can't do so without any overhead. If you need some ordered map, try BTreeMap instead.

2 Likes
#[derive(..., Ord, PartialOrd)]
struct Dimension {...}
...
let mut v: Vec<_> = map.into_iter().collect();
v.sort_by(|x,y| x.0.cmp(&y.0));
1 Like

Thanks, by trying:

println!("{:?}", v[0]);

I got:

((Dimension { item: "A", color: "B", size: "C", part_number: "D" }, "L"), Delivery { variant: Dimension { item: "A", color: "B", size: "C", part_number: "D" }, location: "L", quantity: 15 })

How can I get the Delivery.quantity printed alone.

I believe you can do this:

println!("{:?}", v[0].1.quantity);
1 Like