Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More concise HashMap initialization

Tags:

hashmap

rust

I'm using a HashMap to count the occurrences of different characters in a string:

let text = "GATTACA"; let mut counts: HashMap<char, i32> = HashMap::new(); counts.insert('A', 0); counts.insert('C', 0); counts.insert('G', 0); counts.insert('T', 0);  for c in text.chars() {     match counts.get_mut(&c) {         Some(x) => *x += 1,         None => (),     } } 

Is there a more concise or declarative way to initialize a HashMap? For example in Python I would do:

counts = { 'A': 0, 'C': 0, 'G': 0, 'T': 0 } 

or

counts = { key: 0 for key in 'ACGT' } 
like image 417
anderspitman Avatar asked Feb 08 '15 08:02

anderspitman


2 Answers

Another way that I see in the official documentation:

use std::collections::HashMap;  fn main() {     let timber_resources: HashMap<&str, i32> =     [("Norway", 100),      ("Denmark", 50),      ("Iceland", 10)]      .iter().cloned().collect();     // use the values stored in map } 

EDIT

When I visit the official doc again, I see that the sample is updated (and the old sample is removed). So here is the latest solution with Rust 1.56:

let vikings = HashMap::from([     ("Norway", 25),     ("Denmark", 24),     ("Iceland", 12), ]); 
like image 31
ch271828n Avatar answered Nov 15 '22 21:11

ch271828n


You can use iterators to emulate the dictionary comprehension, e.g.

let counts = "ACGT".chars().map(|c| (c, 0_i32)).collect::<HashMap<_, _>>(); 

or even for c in "ACGT".chars() { counts.insert(c, 0) }.

Also, one can write a macro to allow for concise initialisation of arbitrary values.

macro_rules! hashmap {     ($( $key: expr => $val: expr ),*) => {{          let mut map = ::std::collections::HashMap::new();          $( map.insert($key, $val); )*          map     }} } 

used like let counts = hashmap!['A' => 0, 'C' => 0, 'G' => 0, 'T' => 0];.

like image 166
huon Avatar answered Nov 15 '22 22:11

huon