Geob-o-matic
Geob-o-matic

Reputation: 6079

How do I collect from a nested iterator?

I'm trying to collect from a nested iterator and I get a FromIterator not implemented error. Here's an example:

#[derive(PartialEq)]
enum DayStatus {
    Normal,
    Abnormal,
}

struct Week {
    days: Vec<Day>,
}

struct Day {
    status: DayStatus,
}

struct Month {
    weeks: Vec<Week>,
}

fn get_abnormal_days(month: Month) -> Vec<Day> {
    // assume we have a month: Month which is filled
    month
        .weeks
        .iter()
        .map(|w| w.days.iter().filter(|d| d.status == DayStatus::Abnormal))
        .collect()
}

fn main() {}

Gives me:

 error[E0277]: the trait bound `std::vec::Vec<Day>: std::iter::FromIterator<std::iter::Filter<std::slice::Iter<'_, Day>, [closure@src/main.rs:24:39: 24:74]>>` is not satisfied
  --> src/main.rs:25:10
   |
25 |         .collect()
   |          ^^^^^^^ a collection of type `std::vec::Vec<Day>` cannot be built from an iterator over elements of type `std::iter::Filter<std::slice::Iter<'_, Day>, [closure@src/main.rs:24:39: 24:74]>`
   |
   = help: the trait `std::iter::FromIterator<std::iter::Filter<std::slice::Iter<'_, Day>, [closure@src/main.rs:24:39: 24:74]>>` is not implemented for `std::vec::Vec<Day>`

I could try to impl the FromIterator but the type it has to be from seems too inner to be deal with. I think I'm not calling the proper collect or maybe map but I can't see what I'm missing

My first attempt tried to return &[Day] but it was failing as well.

Upvotes: 4

Views: 5299

Answers (1)

belst
belst

Reputation: 2525

To unnest the iterator, use flat_map instead of map.

Furthermore, you need to either use Copy types or use into_iter to iterate over owned values and not just references.

Working example:

#[derive(PartialEq)]
enum DayStatus {
    Normal,
    Abnormal,
}

struct Week {
    days: Vec<Day>,
}

struct Day {
    status: DayStatus,
}

struct Month {
    weeks: Vec<Week>,
}

fn get_abnormal_days(month: Month) -> Vec<Day> {
    // assume we have a month: Month which is filled
    month
        .weeks
        .into_iter()
        .flat_map(|w| {
            w.days
                .into_iter()
                .filter(|d| d.status == DayStatus::Abnormal)
        })
        .collect()
}

fn main() {}

Upvotes: 6

Related Questions