Oneliner to make vector of tab and comma separated values into HashMap?

Hello everybody!

I have a vector of strings that looks like this ["a\t1", "b,c\t2", "d\t3"]. I would like to make this into a HashMap with these pairs a: 1, b: 2, c: 2, d: 3. So if multiple letters are present before the tab, separated by commas, both of them are made keys with the value that is after the tab. I've already implemented this (the code at the bottom), but I was curious:

Could this be done with a single line/expression? It's probably bad for readability, but it seems possible, if outside of my current Rust skills. Would be very curious to see your solutions!

My implementation:

        for line in respellings_vec{
            let line_tup = (line.split("\t").next().unwrap(), line.split("\t").last().unwrap());
            if line_tup.1.contains(',') {
                for spelling_variant in line_tup.1.split(",").collect::<Vec<&str>>(){
                    reverse_lk.insert(replace_with_precombined(spelling_variant), replace_with_precombined(line_tup.0));
                }
            } else {
                reverse_lk.insert(replace_with_precombined(line_tup.1), replace_with_precombined(line_tup.0));
            }
        }

ps. this implementation is for a slightly different vector, where the the letters/numbers are on opposite sides of the tab

Like this?

let items = ["a\t1", "b,c\t2", "d\t3"];
let map: HashMap<_, _> = items
    .into_iter()
    .flat_map(|item| {
        let (keys, v) = item.split_once('\t').unwrap();
        keys.split(',').map(move |k| (k, v))
    })
    .collect();

TL;DR: use split_once, flat_map and collect.

3 Likes

My observations while reading your code:

  • HashMap can be built from an iterator of pairs, which is easy to produce with flat_map() in this case.
  • There is no reason to have a special case for contains(',') — if you get rid of the unnecessary collect()-then-iterate, then there is no additional cost to just always performing the split.
  • Your split on tabs can be better expressed with str::split_once(), unless there are additional tab-separated fields sometimes present.

…and @paramagnetic beat me to writing out the solution, but I hope this helps you see how to get there.

3 Likes

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.