Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I concisely fill a 2D HashMap?

Tags:

hashmap

rust

Is there a simple way to fill a 2 dimensional HashMap? In C++ I could do something along the lines of:

std::unordered_map<int,std::unordered_map<int,int>> 2dmap;
//...
2dmap[0][0] = 0;
2dmap[0][1] = 1;
//...

In my Rust project I am trying to fill a similar map:

let mut map: HashMap<i32, HashMap<i32, i32>> = HashMap::new();
//...fill the hash map here.

The only way that I can think to do this would be to build each sub map then move them into the super map, something like this:

let mut sub1: HashMap<i32, i32> = HashMap::new();
sub1.insert(0, 0);
sub1.insert(1, 1);
let mut map: HashMap<i32, HashMap<i32, i32>>::new();
map.insert(0, sub1);

Is there a more concise way to do this?

The above code is a simplification of my actual use case which uses an enum as the index of the HashMap:

enum Example {
    Variant1,
    Variant2,
    //...
}

None of the variants hold a value. I am using this syntax for the lookup from my HashMap:

let value = map[Example::Variant1][Example::Variant2];
like image 561
Alex Zywicki Avatar asked Mar 23 '17 18:03

Alex Zywicki


1 Answers

In Rust, tuples work really well. You probably should just use HashMap<(i32, i32), i32>. Then, you end up with something very close to the C++ code.

let mut map: HashMap<(i32, i32), i32> = HashMap::new();
sub1.insert((0, 0), 0);
sub1.insert((0, 1), 1);
// ...

Naturally, it would be nice if we had a macro like vec! for this, and an RFC is in the works. Using the macro from this answer, you can write:

let map = hashmap![(0,0) => 0, (0,1) => 1, ...];

Nothing changes if you are using an enum - just make sure you derive Eq, PartialEq, and Hash for it.

let mut sub1: HashMap<(Example, Example), i32> = HashMap::new();
sub1.insert((Example::Variant1, Example::Variant1), 0);
sub1.insert((Example::Variant1, Example::Variant2), 1);
// ...
like image 90
Alec Avatar answered Sep 24 '22 07:09

Alec