Есть ли итератор, который превращает один элемент итерации во многие? - PullRequest
1 голос
/ 19 апреля 2020

Придуманный пример:

struct ProduceOnes(Vec<usize>);

impl Iterator for ProduceOnes {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        let value = self.0.iter().next()?;

        for _ in 0..*value {
            // I don't want to return, but I want to emit a `Some(1)` for 
            // every iteration of the loop.
            return Some(1);
        }
        unimplemented!()
    }
}

Альтернативой может быть реализация Итератора вместо Item=Vec<usize>, но есть ли альтернатива идиоматизму c для этого?

Детская площадка

1 Ответ

1 голос
/ 20 апреля 2020

Краткий ответ: flat_map.

Другая сложная часть заключается в том, что итератор должен отслеживать свой текущий элемент. Идиоматический c способ заставить ваш пример работать, вероятно, состоит в том, чтобы ввести iter метод, возвращающий фактические Iterator.

struct ProduceOnes(Vec<usize>);

impl ProduceOnes{

    fn iter<'s>(&'s self) -> impl Iterator<Item=usize> + 's {
        self.0.iter().flat_map(|&value| 0..value).map(|_| 1)
    }
}

Полученный итератор будет отслеживать текущий элемент без изменения состояние ProduceOnes. Можем ли мы заставить ваш пример работать, не вводя этот дополнительный метод и не реализуя черту Iterator напрямую? Ответ - да, но нам нужно изменить ProduceOnes, чтобы сделать это. Вот пример итерации по элементам в Ve c.

impl Iterator for ProduceOnes {
    type Item=usize;

    fn next(&mut self) -> Option<usize> {
        match self.0.last_mut() {
            Some(&mut 0) => {
                self.0.pop();
                self.next()
            },
            Some(value) => {
                *value -= 1;
                Some(1)
            }
            None => None
        }
    }
}
.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...