Collecting similar items of iterator by using iterator adapters

Hi!
Let's assume we have a collection of these tuples:

[
   ('t', "tea"),
   ('t', "text"),
   ('t', "task"),
   ('c', "cat"),
   ('c', "crab")
   ('c', "car"),
   ('a', "apple"),
   ('a', "ample"),
]

Is there a way to use some combination of iterator adapters to make this a collection like:

[
   ('t', vec!["tea", "text", "task"]),
   ('c', vec!["cat", "crab", "car"]),
   ('a', vec!["apple", "ample"]),
]

So I would be able to collect this to a HashMap.
I might be being a bit ambiguous here, does the example make sense?

Thanks!

Thanks, but won't this only keep the "task" value for the 't' key only, as the previous values would be overwritten by it? This will collect them into a HashMap<char, &str>, but I need HashMap<char, Vec<&str>>.

Am I missing something?

Sorry, should've payed more attention! This should work:

let mut my_map = HashMap::new();
for (c, s) in my_tuples {
    my_map.entry(&c).or_insert_with(Vec::new).push(s);
}
4 Likes

Thanks, so there is no way to use iterator adapters to modify produce the collection before collecting it to a HashMap?

Why would you want to modify it? It seems to me you want the opposite: a "pure" iterator adaptor solution, that collects directly into a HashMap<String, Vec<_>>. If you are willing to pull in itertools, you can do it with the group_by extension method, as in this Playground.

3 Likes

You can still use iterator adaptors in a for loop, like:

for (c, s) in my_tuples.into_iter().filter(|(c,_)| c.is_lowercase()) {
    my_map.entry(c).or_default().push(s);
}

You could also transform any for loop into a call to for_each or fold, like:

let my_map: HashMap<char, Vec<&str>> = tuples
    .into_iter()
    .filter(|(c,_)| c.is_lowercase())
    .fold(HashMap::new(), |mut map, (c, s)| {
        map.entry(c).or_default().push(s);
        map
    });
4 Likes

Thanks, @H2CO3! I was really looking for a solution like yours and you're right I worded it wrong in my earlier reply!

Thanks, @cole-miller @mbrubeck for your inputs too! :blush: