'How to find X in a HashMap of HashMaps?

Given that I know ParentId and ChildId, how would I find the UserId if the hashmap is:

HashMap<ParentId, HashMap<ChildId, HashMap<UserId, Foobar>>>

As my knowledge about Rust is pretty basic, I found that the following works but it's quite verbose, as I don't know any better:

match foobar.get(&pid) {
  Some(data1) => {
    println!("Found 1: {:?}", data1);

   match data1.get(&cid) {
     Some(data2) => {
      println!("Found 2: {:?}", data2);       
      
      ...and so on
     }, 
     _ => println!("Not found")     
   }
  },
  _ => println!("Not found")
}

I've also attempted chained get but it's tricky and did not find how to do it correctly:

foobar
        .get(pid)?
        .get(cid)?        
        .get(to_find)

What can I try next?



Solution 1:[1]

You can use Option::and_then to chain operations that return Option<_>:

let _: Option<&Foobar> = foobar.get(&pid).and_then(|map| map.get(&cid)).and_then(|map| map.get(&to_find));

Example:

use std::collections::HashMap;

fn main() {
    let map: HashMap<i32, HashMap<bool, HashMap<String, bool>>> = HashMap::new();
    let _: Option<&bool> = map
        .get(&123)
        .and_then(|map| map.get(&true))
        .and_then(|map| map.get("foo"));
}

Playground


Your try with ? is also correct but it'll only work in a function that returns an Option as it returns None from the function the expression is in if any value is None, which is probably the error you're getting.

fn get(map: &HashMap<i32, HashMap<bool, HashMap<String, bool>>>) -> Option<bool> {
    map.get(&123)?.get(&true)?.get("foo").cloned()
}

Edit: As @Jmb pointed out in a comment below, another option is to create and immediately call a closure so you can use the ? operator which could be more readable in certain cases:

let _: Option<&bool> = (|| map.get(&123)?.get(&true)?.get("foo"))();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1