Elegant way to convert vec to map

Is there a more elegant (or idiomatic) way to convert a vec into a map? The usual way i can think of is below:

use std::collections::BTreeMap;

#[derive(Debug, Clone)]
struct Data {
   pub key: String,
   pub val: u32,
}

impl Data {
    pub fn new(key: &str, val: u32) -> Self { Self {key: key.to_string(), val} }
}

fn main() {
    let my_vec = vec![ Data::new("A", 1),Data::new("B", 2),Data::new("C", 3) ];
    let mut my_map = BTreeMap::new();

    for d in my_vec {
        my_map.insert(d.key.clone(), d);  // storing the whole Data as value
    }
    println!("my_map: {:?}", my_map);
}

Note that, since you're consuming the Vec, I don't believe you need to Clone the key value. BTreeMap implements FromIterator for the tuple (K,V), so you can use the collect method:

let my_map: BTreeMap<_, _> = my_vec.into_iter().map(|data| (data.key, data.val)).collect();
4 Likes

Why not use iterator adaptors:

use std::collections::BTreeMap;

#[derive(Debug, Clone)]
struct Data {
   pub key: String,
   pub val: u32,
}

impl Data {
    pub fn new(key: &str, val: u32) -> Self { Self {key: key.to_string(), val} }
}

fn main() {
    let my_vec = vec![ Data::new("A", 1),Data::new("B", 2),Data::new("C", 3) ];
    
    let my_map = my_vec
        .into_iter()
        .map(|x| (x.key.clone(), x))
        .collect::<BTreeMap<_, _>>();
    
    println!("my_map: {:?}", my_map);
}
1 Like

If Data should exist and acts like a key-value pair, tell BTreeMap about it:

impl FromIterator<Data> for BTreeMap<String, u32> {
    fn from_iter<I>(xs: I) -> Self
    where
        I: IntoIterator<Item = Data>,
    {
        xs.into_iter().map(|Data { key, val }| (key, val)).collect()
    }
}

Then simply:

    let my_map = BTreeMap::from_iter(my_vec);

If Data doesn't need to exist, just use tuples, which already work this way.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.