Suprisingly wordy HashMap building with async

Hey,

I'm writing a function that will fetch some info about each of elements passed it and return it as a map. I got it working but it seems super wordy for what it does. I struggled with collect doing the right thing and ended up with extra .into_iter().collect() just to deal with things one a the time (first to pull Result<> and then to actually collect into HashMap).

Can this be done cleaner?

pub async fn get_node_info_map(&self, nodes: &[String]) -> Result<HashMap<String, (String, String)>> {
    let node_info = nodes.iter().map(|node_id| async {
        let node_id = node_id.clone();
        self.get_node_info(&node_id).await
            .map(move |r| (node_id.clone(), r))
    });

    let ret = join_all(node_info)
        .await
        .into_iter()
        .collect::<Result<Vec<_>>>()?
        .into_iter()
        .filter_map(|(k, v)| v.map(|v| (k, v)))
        .collect::<HashMap<_, _>>();

    Ok(ret)
}

pub async fn get_node_info(&self, node_id: &str) -> Result<Option<(String, String)>>

As always, itertools has an option.

     let ret = join_all(node_info)
         .await
         .into_iter()
-        .collect::<Result<Vec<_>>>()?
-        .into_iter()
-        .filter_map(|(k, v)| v.map(|v| (k, v)))
-        .collect::<HashMap<_, _>>();
+        .filter_map_ok(|(k, v)| v.map(|v| (k, v)))
+        .try_collect()?;
3 Likes

You could replace this with try_join_all(node_info)?

1 Like

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.