Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to insert multiple entries into a HashMap at once in Rust?

Tags:

hashmap

rust

Is there any way to insert multiple entries into a HashMap at once in Rust? Or to initialize it with multiple entries? Anything other than manually calling insert on every single element you're inserting?

Edit for an example using English letter frequencies:

I basically want:

let frequencies = { 
  'a': 0.08167, 
  'b': 0.01492, 
  ... 
  'z': 0.00074 
}

I know I can achieve the same result by doing a for loop like the following, but I want to know if there is a way to do this without creating additional arrays and then looping over them, or a more elegant solution in general.

let mut frequencies = HashMap::new();
let letters = ['a','b','c', ...... 'z'];
let freqs = [0.08167, 0.01492, 0.02782, ......., 0.00074];
for i in 0..26 {
    frequencies.insert(letters[i], freqs[i]);
}

For a literal, I could use the answer here, which will probably work fine for this example, but I'm curious whether there's a way to do this without it being a literal, in case this comes up in the future.

like image 319
firechant Avatar asked Jun 15 '17 19:06

firechant


1 Answers

Is there any way to insert multiple entries into a HashMap at once in Rust?

Yes, you can extend a HashMap with values from an Iterator, like this:

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.extend((1..3).map(|n| (format!("{}*2=", n), n * 2)));
    map.extend((7..9).map(|n| (format!("{}*2=", n), n * 2)));
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

It is even a bit faster than calling the insert manually, because extend uses the size hint provided by the Iterator in order to reserve some space beforehand.

Check out the source code of the method here, in map.rs.

Or to initialize it with multiple entries?

This is possible as well, thanks to HashMap implementing the FromIterator trait. When a collection implements FromIterator, you can use the Iterator::collect shorthand to construct it. Consider the following examples, all of them generating the same map:

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<_, _> = (1..3).map(|n| (format!("{}*2=", n), n * 2)).collect();
    map.extend((7..9).map(|n| (format!("{}*2=", n), n * 2)));
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

use std::collections::HashMap;

fn main() {
    let map: HashMap<_, _> = (1..3)
        .chain(7..9)
        .map(|n| (format!("{}*2=", n), n * 2))
        .collect();
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}

use std::collections::HashMap;
use std::iter::FromIterator;

fn main() {
    let iter = (1..3).chain(7..9).map(|n| (format!("{}*2=", n), n * 2));
    let map = HashMap::<String, u32>::from_iter(iter);
    println!("{:?}", map); // Prints {"1*2=": 2, "8*2=": 16, "7*2=": 14, "2*2=": 4}.
}
like image 74
ArtemGr Avatar answered Nov 01 '22 12:11

ArtemGr