Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Тема
Описание
Доп.

Итераторы — это специальные объекты, представляющие последовательный доступ к данным из контейнера. Не загружают весь набор в память а выдают его по требованию (генератор) в отличии от массивов которые изначально полностью загружены в память(К примеру вывод чисел Фибоначи, что сразу массив заполнить?)

Представим, что нам нужен итератор, который реализует последовательность натуральных чисел. Или чисел Фибоначчи. Или любую другую бесконечную последовательность. В массиве сложно разместить бесконечную последовательность, понадобится механизм постепенного наполнения массива данными, а также изъятия старых данных, чтобы не заполнить всю память процесса.

📌 async iterators

В Rust на текущий момент поддержка async iterators реализована как экспериментальная функциональность и доступна только в nightly версиях компилятора. Основной API представлен через трейты, такие как AsyncIterator, который предоставляет асинхронный вариант стандартного Iterator. Этот функционал позволяет работать с последовательностями значений, поступающих асинхронно, что полезно в потоках данных или других сценариях, где события происходят не одновременно.

Работа над async iterators продолжается, и они еще не полностью интегрированы в стабильную версию компилятора. Эти улучшения активно обсуждаются, и их возможная интеграция в стандартную библиотеку планируется в будущем, вероятно, в 2024 году, что может совпасть с выпуском новой версии языка.

Если вы хотите попробовать их сейчас, потребуется nightly версия Rust и включение соответствующего feature-флага, например #![feature(async_iterator)].

На данный момент в Rust активно используется асинхронность через async/await и асинхронные функции. Однако текущая модель асинхронности чаще работает с сущностями типа Future, которые представляют собой единичные асинхронные операции, возвращающие результат в будущем.

Async iterators же расширяют возможности, позволяя работать с потоками данных (аналогично Iterator для синхронного кода). Основное различие — в парадигме обработки:

Асинхронные функции (async): решают задачи, где требуется одна операция или одно значение (например, отправка HTTP-запроса). Async iterators: решают задачи, где поступают множество значений асинхронно, одно за другим, например, обработка потока событий или чтение больших данных по частям.


Async iterators в Rust полезны в сценариях, где необходимо обрабатывать потоки данных или событий, которые поступают асинхронно. Вот несколько примеров, где это может быть полезно:

1. Обработка потоков данных Если данные поступают из внешнего источника, например, через сеть или файловую систему, async iterators позволяют их обрабатывать по мере поступления. Это может быть полезно для:

  • Чтения логов или больших файлов частями.
  • Обработки сообщений в очереди, например, из Kafka или RabbitMQ.

2. Работа с асинхронными API

  • Интеграция с потоковыми API, такими как WebSocket или Server-Sent Events (SSE).
  • Обработка последовательных запросов к API, которые возвращают набор данных по частям (например, пагинация).

3. Реактивные системы В системах, построенных на событийной модели, async iterators позволяют обрабатывать входящие события или данные в реальном времени, например:

  • Обработка сенсорных данных в IoT-приложениях.
  • Реализация реактивных пользовательских интерфейсов (например, асинхронная обработка пользовательского ввода).

4. Параллельная обработка Используя методы, такие как for_each_concurrent, можно обрабатывать элементы в потоке параллельно, что увеличивает производительность в задачах, связанных с интенсивной асинхронной обработкой.

5. Сложные пайплайны данных Async iterators облегчают создание сложных цепочек обработки данных с возможностью фильтрации, объединения, разбивки на группы и других операций.

Пример:

Представьте, что вы читаете данные из базы данных порциями и сразу передаете их на обработку:


async fn fetch_data() -> impl AsyncIterator> {
    // Возвращает поток асинхронных данных
}
fn main(){
 let mut data_stream = fetch_data();
 while let Some(data) = data_stream.next().await {
    match data {
        Ok(item) => process(item).await,
        Err(err) => handle_error(err),
    }
 }
}

Итог:

Async iterators полезны в любом сценарии, где асинхронная обработка данных с сохранением простоты и читаемости кода является критически важной. Это улучшает производительность и снижает сложность кода в современных асинхронных приложениях.

std::ops::Range

(Полуоткрытый) диапазон

struct.Range


fn main(){
    assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });// 3, 4
}


fn main(){
    let bounded: std::ops::Range = 0..10;
    for i in bounded{
        print!("{i}");
    }
}


fn main(){
    let from = 0..;
    let to = ..10;
    let full = ..;
    let inclusive = 0..=9;
    for i in (0..10).step_by(2) {
        println!("i = {}", i);
    }
// Пo lo..hi и lo.. можно итерироваться
}

Trait std::ops::Generator

📌 УСТАРЕЛ Nightly

yield

trait.Generator

generators

This is a nightly-only experimental API

Генератор — это «возобновляемая функция», которая синтаксически напоминает замыкание, но компилируется в самом компиляторе с совершенно другой семантикой. Генеративный итератор в котором не нужно менеджерить состояние. Основная особенность генератора заключается в том, что его можно приостановить во время выполнения, чтобы возобновить позже в отличие от итераторов. Генераторы используют yield ключевое слово для «возврата», а затем вызывающая сторона может resume возобновить выполнение генератора сразу после yield ключевого слова.

Сопрограмма

Generators это сопрограмма, т.е. поток исполнения кода поверх системных потоков. Поток исполнения это последовательность операций выполняющихся друг за другом. Она исполняется пока не наступит определенный момент заданный в коде.

Generators

В настоящее время основным предполагаемым вариантом использования генераторов является реализация примитива для синтаксиса async/await Всякий раз, когда генератор удаляется, он удаляет все захваченные переменные среды Генератор выполняет свой код до команды yield и сохраняет свое состояние до следующего вызова resume (конечные автоматы)

pub trait std::ops::Generator<R = ()> {
    type Yield;
    type Return;
    fn resume(self: std::pin::Pin<&mut Self>, resume: R) -> std::ops::GeneratorState<Self::Yield, Self::Return>;
}
pub enum std::ops::GeneratorState<Y, R> {
    Yielded(Y),
    Complete(R),
}

Где std::pin::Pin это тип реализующий

std::ops::Coroutine

📌 std::ops::Coroutine


#![feature(coroutines, coroutine_trait)]
#![feature(stmt_expr_attributes)]

use std::ops::{Coroutine, CoroutineState};
use std::pin::Pin;

pub fn main() {
    let one: &str = "1";
    let three = String::from("3");
    let ret: &str = "hello";
    
    let mut coroutine = #[coroutine]
    move || {
        println!("{}", one);
        yield 1;
        println!("{}", three);
        ret // возвращаемое значение
    };
     
    // Первый вызов - до первого yield
    match Pin::new(&mut coroutine).resume(()) {
        CoroutineState::Yielded(1) => {}
        _ => panic!("unexpected value from resume"),
    }
    
    println!("2");
    
    // Второй вызов - после yield до завершения
    match Pin::new(&mut coroutine).resume(()) {
        CoroutineState::Complete(s) if s == "hello" => {}
        _ => panic!("unexpected value from resume"),
    }
    
    println!("4");
}

Run:

cargo +nightly run

📌 async + Streams (через crates вроде futures)


use futures::stream::{self, StreamExt};

#[tokio::main]
async fn main() {
    let mut stream = stream::iter(vec![1, 2, 3]);
    while let Some(val) = stream.next().await {
        println!("{}", val);
    }
}

Тип, целью которого является многократная выдача следующего элемента контейнера, пока он не будет исчерпан

  • IntoIter - T
  • IterMut - &mut T
  • **Iter - &T **

Итераторы также являются компонуемыми, и обычно их объединяют в цепочку (адаптеры делают возможным Функции высшего порядка) для выполнения более сложных форм обработки

Итераторы ленивы т.е. это v.iter().map(|x| println!("{x}")); ничего не выведет (v.iter().for_each не ленив)


fn main(){
// Компилятор автоматически использует std::iter::Iterator для выражений вида:
    for item in collection {
        // body
    }

// эффективно преобразуя их в код примерно такого вида:
    let mut iter = collection.into_iter();
    loop {
        let item: Thing = match iter.next() {
            Some(item) => item,
            None => break,
        };
        // body
    }

// или более кратко и идиоматично:
    let mut iter = collection.into_iter();
    while let Some(item) = iter.next() {
        // body
    }
}

Преобразование цикла в функциональном стиле

effective-rust/iterators


fn main(){
    let mut even_sum_squares = 0;
    let mut even_count = 0;
    for i in 0..values.len() {
        if values[i] % 2 != 0 {
            continue;
        }
        even_sum_squares += values[i] * values[i];
        even_count += 1;
        if even_count == 5 {
            break;
        }
    }

// Преобразование:
    let even_sum_squares: u64 = values
        .iter()
        .filter(|x| *x % 2 == 0)
        .take(5)
        .map(|x| x * x)
        .sum();
}

Ленивость итераторов

В Rust итераторы ленивы, то есть они не действуют, пока вы не вызовете методы, которые используют итератор для его использования.


fn main(){
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
// v1_iter ничего не потребляет ресурсы, он в ожидании
    for val in v1_iter {
        // теперь тянем по одному элементу затрагивая ресурсы процессора
        println!("Got: {}", val);
    } 
}

Вернуть Iterator/Filter


fn filter_one(input: &[u8]) -> impl Iterator {
    input.iter().filter(|&&x| x == 1)
}

fn main() {
    let nums = vec![1, 2, 3, 1, 2, 3];
    let other: Vec<_> = filter_one(&nums).collect();
    println!("{:?}", other);
}

std::iter::IntoIterator для преобразования чего-либо в итератор std::iter::Iterator

IntoIterator поставляется с методом into_iter(), который возвращает итератор по своему значению

Любой реализующий тип IntoIterator также называется Iterable


fn main(){
    // Vec реализует IntoIterator:
    let values = vec![1,2,3];
    let mut iter = IntoIterator::into_iter(values);// либо values.into_iter();
    let _:i32 = iter.next().unwrap();
}

into_iter потребляем коллекцию

Инструкция for in неявно вызывает для коллекции реализацию into_iter которая потребляет коллекцию и она после недоступна


fn main(){
    let xs = [1,2,3];
    let xs = vec![1,2,3];
    let mut it = xs.into_iter();
    while let Some(x) = it.next() {
        println!("{:?}",x);    
    }
}

Для реализации std::iter::IntoIterator для типа A необходимо:

  • реализовать std::iter::Iterator для оболочки WraperA
  • а для A реализовать std::iter::IntoIterator

Для возможности использовать ссылку для into_iter() следует реализовать IntoIterator for &'a A и impl<'a> IntoIterator for &'a mut A

(Если тип является итерируемым, мы почти всегда используем некий пользовательский тип итератора, который выполняет итерацию по нему, а не пытается заставить его выполнять итерацию по самому себе)

Если для типов IntoIterator есть реализации по ссылке, то не будет потребления значения

impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>

struct A{
    value:Vec
}
impl std::iter::IntoIterator for A {
    type Item = i32;
    type IntoIter = WraperA;
    fn into_iter(self) -> Self::IntoIter{
        WraperA::new(self.value)
    }
}
impl<'a> IntoIterator for &'a mut A{
    type Item = i32;
    type IntoIter = RefWraperA<'a>;
    fn into_iter(self) -> Self::IntoIter{
        RefWraperA::new(self)
    }
}
impl<'a> IntoIterator for &'a A {
    type Item = i32;
    type IntoIter = RefWraperA<'a>;
    fn into_iter(self) -> Self::IntoIter{
        RefWraperA::new(self)
    }
}
struct WraperA(usize,A);
impl WraperA{
    fn new(value:Vec)->Self{
        Self(0,A{value})
    }
} 
impl std::iter::Iterator for WraperA {
    type Item = i32;
    fn next(&mut self) -> Option {
        if self.0 < self.1.value.len() {
            self.0+=1;println!("+++");
            return Some(*self.1.value.get(self.0-1).unwrap());
        }
        None
    }
}
struct RefWraperA<'a>(usize,&'a A);
impl<'a> RefWraperA<'a>{
    fn new(a:&'a A)->Self{
        Self(0,a)
    }
} 
impl<'a> std::iter::Iterator for RefWraperA<'a> {
    type Item = i32;
    fn next(&mut self) -> Option {
        if self.1.value.len() > self.0 {
            self.0+=1;
            return Some(*self.1.value.get(self.0-1).unwrap());
        }
        None
    }
}

fn main() {
// impl WraperA
    let a = A{value:vec![1,2,3]};
    let mut iter = a.into_iter();
    assert_eq!(iter.next(),Some(1));
    assert_eq!(iter.next(),Some(2));
    assert_eq!(iter.next(),Some(3));
    assert_eq!(iter.next(),None);

// для impl RefWraperA<'a> 
// impl<'a> IntoIterator for &'a mut A
// impl<'a> IntoIterator for &'a A
   
    let mut a = A{value:vec![1,2,3]};
    let mut iter = (& a).into_iter();
    assert_eq!(iter.next(),Some(1));
    assert_eq!(iter.next(),Some(2));
    assert_eq!(iter.next(),Some(3));
    assert_eq!(iter.next(),None);
// второй раз используем
    for v in a {print!("{v}");}
}

struct Iter<'a, T: 'a> {
    vec: &'a [T],
    index: usize,
    f: Box bool>
}

impl<'a, T: 'a> Iter<'a, T> {
    fn new(vec: &'a [T], f: F) -> Self
    where
        F: Fn(T) -> bool + 'static
    {
        Self {
            vec,
            index: 0,
            f: Box::new(f)
        }
    }
}

impl<'a, T: 'a + Copy> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option {
        while self.index < self.vec.len() - 1 {
            let prev = self.vec[self.index];
            self.index += 1;
            if (self.f)(prev) {
                return Some(self.vec[self.index]);
            }
        }
        None
    }
}

fn main() {
    let vec = vec![4u8, 5, 6, 7, 1, 9, 0, 3];
    let mut iter = Iter::new(&vec, |x| x % 3 == 0);

    for num in iter {
        print!("{}, ", num);
    }
    println!();
}

Реализация IterMut

IterMut::next ЭТО МУТАБЕЛЬНАЯ ССЫЛКА НА ДАННЫЕ ПЕРВОИСТОЧНИКА КАЖДАЯ ИТЕРАЦИЯ ЭТО УНИКАЛЬНАЯ МУТАБЕЛЬНАЯ ССЫЛКА ПОЭТОМУ ЕЕ СЛЕДУЕТ ПОДМЕНЯТЬ НА СЛЕДУЮЩИЕ ДАННЫЕ ПЕРВОИСТОЧНИКА ПОДМЕН В ПАМЯТИ ДЛЯ Option<> метод take() ДЛЯ других типов std::mem::replace(&mut self.next, None)

digitrain.ru/questions/61978903

second-iter-mut

pub struct List<T> {
    head: Option<Box<Node<T>>>
}
struct Node<T> {
    elem: T,
    next:  Option<Box<Node<T>>>
}
impl<T> List<T> {
    pub fn new() -> Self {
        List { head: None }
    }

    pub fn push(&mut self, elem: T) {
        let new_node = Box::new(Node {
            elem: elem,
            next: self.head.take(),
        });

        self.head = Some(new_node);
    }
    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
        IterMut { next: self.head.as_deref_mut() }
    }
}
pub struct IterMut<'a, T> {
    next: Option<&'a mut Node<T>>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
// Метод Option::take подменяет значение в памяти как std::mem::replace 
// и находим новую ссылку для self.next 
        self.next.take().map(|node| {
            self.next = node.next.as_deref_mut();
            &mut node.elem
        })
    }
}

#[cfg(test)]
mod test {
    use super::{Node,List};
    #[test]
    fn iter_mut() {
        let mut list  = List::new();
        list.push(1); list.push(2); list.push(3);

        let mut iter = list.iter_mut();
        assert_eq!(iter.next(), Some(&mut 3));
        assert_eq!(iter.next(), Some(&mut 2));
        assert_eq!(iter.next(), Some(&mut 1));
        
        for i in list.iter_mut(){
            println!("{}",i);
        }
        for i in list.iter_mut(){
            println!("{}",i);
        }
    }
}
fn main(){}

Три типа итератора для реализации вашими коллекциями:

  • IntoIter - T
  • IterMut - &mut T
  • Iter - &T

second-iter-mut

stackoverflow/38089723

digitrain/61978903

Владеющий итератор IntoIter

use std::iter::Iterator;
struct Foo<T>{
   data:Vec<T>
}

pub struct WrapIntoIter<T>(Foo<T>);
impl<T> Foo<T> {
    pub fn into_iter(self) -> WrapIntoIter<T> {
        WrapIntoIter(self)
    }
}
impl<T> Iterator for WrapIntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        // access fields of a tuple struct numerically
        self.0.data.pop()
    }
}
fn main(){}

Заимствующий итератор shared Iter


pub struct WrapIter<'a, T> {
    current_index:usize,
    next: &'a Foo<T>,
}
// Здесь нет времени жизни,так как Foo не имеет связанных сроков жизни
impl<T> Foo<T> {
    pub fn iter<'a>(&'a self) -> WrapIter<'a, T> {
        WrapIter{current_index:0,next: self }
    }
}
impl<'a, T> Iterator for WrapIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
       // своя логика того как отдавать по очереди данные и поля WrapIter структуры в помощь
       if self.current_index < self.next.data.len(){
           self.current_index+=1;
           return Some(&self.next.data[self.current_index-1]);
       }
       None
    }
}
fn main(){}

Мутирующее заимствование IterMut

pub struct WrapIterMut<'a, T> {
    current_index:usize,
    next:  &'a mut Vec<T>
}
impl<T> Foo<T> {
    pub fn iter_mut<'a>(&'a mut self) -> WrapIterMut<'a, T> {
        WrapIterMut{current_index:0,n: self.data.len(), next:  &mut self.data }
    }
}
impl<'a, T: std::fmt::Debug + Default> Iterator for WrapIterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        // своя логика того как отдавать по очереди данные и поля WrapIter структуры в помощь
            let result = unsafe {
            match self.current_index {
                // Безопасность: Поскольку каждая из этих трех ветвей
                // выполняется ровно один раз, мы выдаем не более одной изменяемой ссылки к каждой части self.next
                // Так как self.next действителен для 'a. Каждое частичное заимствование также допустимо для 'a
                n if n < self.n => &mut *(&mut self.next[self.current_index] as *mut _),
               // n if n < self.n => &mut *(self.next.get_mut(self.current_index).unwrap() as *mut _),
                _ => return None
            }
        };
        // Если self.index не равен 0, 1 или 2, мы уже вернули
        // Так что это поднимает нас до 1, 2 или 3.
        self.current_index += 1;
        Some(result)
    }
}
fn main() {
    let foo:Foo<i32> = Foo{data:vec![1,2,3]};
    let mut iter = foo.into_iter();
    assert_eq!(iter.next(), Some(3)); assert_eq!(iter.next(), Some(2));assert_eq!(iter.next(), Some(1)); assert_eq!(iter.next(), None);
     
    let foo:Foo<i32> = Foo{data:vec![1,2,3]};
    for i in foo.into_iter() { // владеющий цикл также доступен, благодаря impl<T> Iterator
        println!("{}",i);
    }
     
    let foo:Foo<i32> = Foo{data:vec![1,2,3]};
    for i in foo.iter() { println!("{}",i); } // общее заимствование, благодаря WrapIter
    for i in foo.iter() { println!("{}",i);}
   
    let mut foo:Foo<i32> = Foo{data:vec![1,2,3]};
    for i in foo.iter_mut() { // мутирующее заимствование, благодаря WrapIterMut
        println!("iter_mut {}",i);
    }
}

Функция принимающая итератор


fn find_max(iter: I) -> Option
  where I: Iterator,
             I::Item: Ord { 
    iter.reduce(|a, b| {
        if a >= b { a } else { b }
    })
}
fn main(){
    let a = [10, 20, 5, -23, 0];
    let b: [u32; 0] = [];
    assert_eq!(find_max(a.iter()), Some(&20));
    assert_eq!(find_max(b.iter()), None);
}

Функция принимающая итератор по значению

impl<I: Iterator + ?Sized> Iterator for &mut I;

любая изменяемая ссылка на итератор также является итератором т.е. можем вызывать self методы тоже помимо &self и &mut self


fn example>(mut iter: I) {
    let first3: Vec = iter.by_ref().take(3).collect(); // возьмем ссылку чтобы можно было использовать iter повторно в for 
    for item in iter { 
        // process remaining items
    }
}
fn main(){
    example(1..10); // 1..10 реализует Iterator

    let v = vec![10, 20, 30, 40, 50];
    example(v.into_iter()); // into_iter() делает итератор по i32

    let v = vec![10, 20, 30, 40, 50];
    example(v.into_iter());  

    let mut n = 0;
    let gen = std::iter::from_fn(move || {
        n += 1;
        if n <= 7 { Some(n * 10) } else { None }
    });
    example(gen);
}

Цикл с итератором


fn main(){
    let v = vec![1, 5];
    let mut iter = v.iter();                       
    loop {
        let value = iter.next();                   
        if value.is_some() {
            println!("value: {}", value.unwrap());
        } else {
            break;
        }
    }
}

Реализация итератора на структуру Фибоначчи


struct Fibonacci {
    curr: u32,
    next: u32,
}

// Реализация `Iterator` для `Fibonacci`.
// Для реализации типажа `Iterator` требуется реализовать метод `next`.
impl Iterator for Fibonacci {
    type Item = u32;

    // Здесь мы определяем последовательность, используя `.curr` и `.next`.
    // Возвращаем тип `Option`:
    //     * Когда в `Iterator` больше нет значений, будет возвращено `None`.
    //     * В противном случае следующее значение оборачивается в `Some` и возвращается.
    fn next(&mut self) -> Option {
        let new_next = self.curr + self.next;

        self.curr = self.next;
        self.next = new_next;

        // Поскольку последовательность Фибоначчи бесконечна,
        // то `Iterator` никогда не вернет `None`, и всегда будет
        // возвращаться `Some`.
        Some(self.curr)
    }
}

// Возвращается генератор последовательности Фибоначчи.
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // `0..3` это `Iterator`, который генерирует : 0, 1, и 2.
    let mut sequence = 0..3;

    println!("Четыре подряд вызова `next`на 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for` работает через `Iterator` пока тот не вернет `None`.
    // каждое значение `Some` распаковывается  и привязывается к переменной (здесь это `i`).
    println!("Итерирование по 0..3 используя `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // Метод `take(n)` уменьшает `Iterator` до его первых `n` членов.
    println!("Первые четыре члена последовательности Фибоначчи: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // Метод `skip(n)` сокращает `Iterator`, отбрасывая его первые `n` членов.
    println!("Следующие четыре члена последовательности Фибоначчи: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // Метод `iter` превращает `Iterator` в массив/срез.
    println!("Итерирование по массиву {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}

std::iter::FromIterator

С его помощью можно преобразовать одну коллекцию (т.е. итератор) в коллекцию другого типа (т.е. итератор). Для типов без реализации Iterator::collect()

trait.FromIterator


use std::iter::FromIterator;
#[derive(Debug)]
struct MyCollection(Vec);

impl MyCollection {
    fn new() -> MyCollection {
        MyCollection(Vec::new())
    }
    fn add(&mut self, elem: i32) {
        self.0.push(elem);
    }
}
impl FromIterator for MyCollection {
    fn from_iter>(iter: I) -> Self {
        let mut c = MyCollection::new();
        for i in iter {
            c.add(i);
        }
        c
    }
}
fn main(){
    let iter = (0..5).into_iter();
    let c: MyCollection = iter.collect();
    assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
    //-----------------------------------------------------
    let iter = (0..5).into_iter();
    let c = MyCollection::from_iter(iter);
    assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
    //-----------------------------------------------------
   // Result реализуется FromIterator, поэтому collect() должен работать.
   // При первом обнаружении Errварианта он возвращает этот вариант и прекращает сбор.

    let results = [Ok(1), Err("nope"), Ok(3), Err("bad")];
    let result: Result, &str> = results.iter().cloned().collect();
    // дает нам первую ошибку
    assert_eq!(Err("nope"), result);
    let results = [Ok(1), Ok(3)];
    let result: Result, &str> = results.iter().cloned().collect();
    // дает нам список ответов
    assert_eq!(Ok(vec![1, 3]), result);
}

вы можете создать Vec из в Iterator благодаря FromIterator


struct Foo {
    count: u8
}
impl Iterator for Foo {                           
    type Item = u8;
    fn next(&mut self) -> Option {
        match self.count {
            0 => {
                self.count = self.count + 1;
                Option::Some(1)                   
            }
            1 => {
                self.count = self.count + 1;
                Option::Some(5)                   
            }
            _ => None                             
        }
    }
}
fn main(){
    let i = Foo { count: 0 };
    let v = Vec::from_iter(i);                        
    for value in v {
        println!("value: {}", value);
    }
}

Собственный адаптер, реализация filter


struct Filter {
    iter: I,
    predicate: F,
}
impl Iterator for Filter
where
  I: Iterator,
  F: FnMut(&I::Item) -> bool {
    type Item = I::Item;
    fn next(&mut self) -> Option {
        while let Some(item) = self.iter.next() {
            if (self.predicate)(&item) { return Some(item); }
        }
        None
    }
}
fn filter(iter: I, predicate: F) -> impl Iterator
where
    I: IntoIterator,
    F: FnMut(&I::Item) -> bool {
    Filter {
        iter: iter.into_iter(),
        predicate,
    }
}
fn main() {
    let even_numbers = filter(0..10, |n| n % 2 == 0);
    for number in even_numbers { println!("{}", number);}
}

Можно собирать итераторы в Result или Option

collect

Можно собирать итераторы в Result или Option


fn main(){
    let items = vec![3_u16, 2, 1/*, 0*/];
    let res: Option> = items
      .iter()
      .map(|x| x.checked_sub(1))// трансформируем значение в Option
      .collect();// достаются значения из Some иначе результат None
    println!("{:?}",res);// Some([2, 1, 0])
}

Функции высшего порядка FVP


fn main(){
 let upper = 1000;
    fn is_odd(n: u32) -> bool {
       n % 2 == 1
    }
    // Функциональный подход
    let sum_of_squared_odd_numbers: u32 =
        (0..).map(|n| n * n)             // Все натуральные числа в квадрате
             .take_while(|&n| n < upper) // Ниже верхнего предела
             .filter(|n| is_odd(*n))     // Это нечётные
             .fold(0, |sum, i| sum + i); // Суммируем
    println!("functional style: {}", sum_of_squared_odd_numbers);
}

Чем меньше предположений функция делает о своих входных данных, тем шире она становится

fn foo<I: IntoIterator<Item = i64>>(iter: I) { /* ... */ }

// заменяет все:

fn foo(c: &[i64]) { /* ... */ }
fn foo(c: &Vec<i64>) { /* ... */ }
fn foo(c: &SomeOtherCollection<i64>) { /* ... */ }

fn get_nums(a: u32, b: u32) -> impl Iterator<Item = u32> {
    (a..b).filter(|x| x % 100 == 0)
}
fn main() {
    for n in get_nums(100, 1001) {
        println!("{}", n);
    }
}

Iterator

std::iter::Peekable

(Возвращает ссылку на значение next() без перемещения итератора)

struct.Peekable


use std::iter::Peekable;
struct InefficientChunks where I: Iterator {
    iter: Peekable,
    size: usize,
}
impl Iterator for InefficientChunks where I: Iterator {
    type Item = Vec;
    fn next(&mut self) -> Option {
        if self.iter.peek().is_some() {
            Some(self.iter.by_ref().take(self.size).collect())
        } else {
            None
        }
    }
}
trait Awesome: Iterator + Sized {
    fn inefficient_chunks(self, size: usize) -> InefficientChunks {
        InefficientChunks {
            iter: self.peekable(),
            size: size,
        }
    }
}
impl Awesome for I where I: Iterator {}

fn main() {
    for chunk in (1..100).inefficient_chunks(5) {
        println!("{:?}", chunk);
    }
}


fn main(){
  let xs = [1, 2, 3];
  let mut iter = xs.iter().peekable();
  // peek() lets us see into the future
  assert_eq!(iter.peek(), Some(&&1));
  assert_eq!(iter.next(), Some(&1));
}
  • next(&mut self) -> Option<&'t str> - Увеличивает итератор и возвращает следующее значение
  • for_each<F>(self, f: F) - Вызывает замыкание на каждом элементе итератора.
  • inspect<F>(self, f: F) -> Inspect<Self, F> - в качестве инструмента отладки встраивания на различных участках конвейера итераторов
  • all<F>(&mut self, f: F) -> bool - проверка соответствия всех элементов условию ф-цию Останавливается на первом false
  • any<F>(&mut self, f: F) -> bool - проверка наличия любого элемента который удовлетворяет ф-цию Останавливается на первом true
  • is_sorted(), is_sorted_by(), is_sorted_by_key() - Проверяет, отсортированы ли элементы этого итератора.
  • is_partitioned() - Проверяет, разделен ли итератор в соответствии с заданным предикатом
  • collect_into() - Собирает все элементы итератора в коллекцию.
  • partition_in_place() - Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом.Возвращает количество true элементов.

Потребители:

  • collect() -> B where B: FromIterator<T> - Преобразует все значения итератора в коллекцию
  • try_collect() - Преобразует все Some/Ok/ControlFlow::Continue значения итератора в коллекцию до None/Err или после
  • fold(S, (S, T) -> S) -> S - Получить одно значение на основе ф-ии предиката обработки итератора
  • try_fold<B, F, R>(&mut self, init: B, f: F) -> R - как fold() но возвращает Option/Result
  • partition((&T) -> bool) -> (B, B) where B: Default + Extend<T> - Создает две коллекции из итератора
  • find((&T) -> bool) -> Option<T> - возвращает первый элемент удовлетворивший условие замыкания
  • try_find() - Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку
  • find_map((T) -> Option<U>) -> Option<U> - возвращает первый элемент с результатом Some
  • position((T) -> bool) -> Option<usize> - Ищет элемент в итераторе, возвращая его индекс.
  • rposition((T) -> bool) -> Option<usize> - как position но начинает с конца
  • last(self) -> Option<Self::Item> - Расходует итератор, возвращая последний элемент.
  • count() -> usize - Расходует итератор, подсчитывает количество итераций и возвращает его
  • sum<S>(self) -> S - Суммирует элементы итератора Может паниковать
  • product()-> P where P: Product<T> - умножение всех элементов на предыдущий результат
  • nth(&mut self, n: usize) -> Option<Self::Item> - Возвращает n-й элемент итератора.Забирает элемент
  • try_for_each<F, R>(&mut self, f: F) -> R - продолжает перебор до первого Err результата и вернет его
  • next_chunk() - Перемещает итератор и возвращает массив, содержащий следующие N значения
  • max() -> Option<T> - Возвращает максимальный элемент итератора.
  • min() -> Option<T> - Возвращает минимальный элемент итератора.
  • max_by((&T, &T) -> Ordering) -> Option<T> - элемент давший максимальное значение из функции
  • min_by((&T, &T) -> Ordering) -> Option<T> - элемент давший минимальное значение из функции
  • max_by_key((&T) -> U) -> Option<T> - элемент давший максимальное значение из функции
  • min_by_key((&T) -> U) -> Option<T> - элемент давший минимальное значение из функции
  • size_hint(&self) -> (usize, Option<usize>) - Возвращает границы (min,max) на оставшейся длине итератор
  • reduce<F>(self, f: F) -> Option<Self::Item> - Сводит итератор к одному значению
  • try_reduce() - Уменьшает элементы до одного, многократно применяя операцию сокращения.

Адаптеры:

  • map((T) -> U) -> Iterator<Item = U> - преобразует значения итератора в другой вид
  • map_windows() - Преобразует данные функцией каждого непрерывного окна размером N
  • filter((&T) -> bool) -> Iterator<Item = T> - фильтрует ел. ф-ей предикатом
  • filter_map((T) -> Option<U>) -> Iterator<Item = U> - фильтрует ел. ф-ей предикатом и преобразует
  • peekable(self) -> Peekable<Self> - Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора, не потребляя его.
  • intersperse() - Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора. (для Clone)
  • intersperse_with() - как intersperse но для Copy
  • skip(usize) -> Iterator<Item = T> - Создает итератор, который пропускает первые n элементов.
  • take(usize) -> Iterator<Item = T> - Создает итератор, со следующими n элементами.
  • skip_while((&T) -> bool) -> Iterator<Item = T> - как skip() но решение принимает ф-ия предикат.
  • take_while((&T) -> bool) -> Iterator<Item = T> - как take() но при условии выполнения ф-ия предиката
  • map_while() - Создает итератор, который возвращает элементы на основе предиката и сопоставлений. Потребляет значения
  • step_by(usize) -> Iterator<Item = T> - Создает итератор с измененным шагом итерации
  • enumerate()->Iterator<Item=(usize, T)> - Создает итератор с текущее количество итераций и значением.
  • advance_by(usize)->Result<(), NonZeroUsize> - Перемещает итератор вперед по nэлементам
  • chain(IntoIterator<Item = T>) -> Iterator<Item = T> - дописывает итератор в конец итератора
  • zip(IntoIterator<Item=U>)->Iterator<Item=(T,U)> - два итератора в один итератор пар соответствии позиции
  • array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> - Возвращает итератор по N элементам итератора одновременно
  • unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) - потребляет весь итератор пар, создавая две коллекции: одну из левых элементов пар и одну из правых элементов.
  • scan(S, (&mut S, T) -> Option<U>) -> Iterator<Item = U> - как fold но возвращает новый итератор
  • fuse(self) -> Fuse<Self> - Создает итератор, который заканчивается после первого [None]
  • rev() -> Iterator<Item = T> - Изменяет направление итератора на обратное
  • cycle() -> Iterator<Item = T> where Self: Clone - Повторяет итератор бесконечно
  • cloned() -> Iterator<T> where T: Clone - Создает итератор, который клонирует все его элементы ссылки
  • copied() -> Iterator<T> where T: Copy - Создает итератор, который копирует все его элементы. Это полезно, когда у вас есть итератор над &T, но вам нужен итератор над T.
  • by_ref(&mut self) -> &mut Self - Заимствует итератор, а не потребляет его. Это полезно, чтобы разрешить применение адаптеров итератора при сохранении права собственности на исходный итератор.
  • flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> - Создает итератор, который работает как map, но выравнивает вложенную структуру. Замыкание map возвращает один элемент для каждого элемента, а Замыкание flat_map () возвращает итератор для каждого элемента. превращает элемент в последовательность
  • flatten(self) -> Flatten<Self> - Создает итератор, выравнивающий вложенную структуру. (хотите удалить один уровень косвенности)

Функции:

  • from_generator() - Создает новый итератор, где каждая итерация вызывает предоставленный генератор.
  • empty() - Создает итератор, который ничего не дает.
  • from_fn() - Создает новый итератор, где каждая итерация вызывает предоставленное замыкание F: FnMut() -> Option<T>.
  • once( )- Создает итератор, который возвращает элемент ровно один раз.
  • once_with() - Создает итератор, который лениво генерирует значение ровно один раз, вызывая предоставленное закрытие.
  • repeat() - Создает новый итератор, который бесконечно повторяет один элемент.
  • repeat_with() - Создает новый итератор, который бесконечно повторяет элементы типа, применяя предоставленное замыкание, повторитель, F: FnMut() -> A.
  • successors() - Создает новый итератор, в котором каждый последующий элемент вычисляется на основе предыдущего.
  • zip() - Преобразует аргументы в итераторы и архивирует их.

create Iterator


fn main(){
    let iter1 = 0..10;
    let mut names = &mut vec![1, 2, 3];
    let iter2 = names.iter_mut();
    let iter3 = [10, 20, 30,40,50].iter();
    let iter3 = [10, 20, 30,40,50].into_iter();
    let iter4 = "привет".char_indices();
    let iter5 = "привет".bytes();
    let iter6 = "МИР\tТРУД МАЙ".split_whitespace();
    let iter7 = "foo\r\nbar\n\nbaz\n".lines();
    let iter8 = "abcXXXabcYYYabc".matches("abc");
}

next(&mut self) -> Option<&'t str> - Увеличивает итератор и возвращает следующее значение


fn main(){
    let a = [1, 2, 3];
    let mut iter = a.iter();
    assert_eq!(Some(&1), iter.next());
    assert_eq!(Some(&2), iter.next());
}

for_each<F>(self, f: F) - Вызывает замыкание на каждом элементе итератора.

Это эквивалентно использованию for цикла на итераторе, хотя break и continue невозможно из закрытия. Как правило, более идиоматично использовать for цикл, но for_each может быть более разборчивым при обработке элементов в конце более длинных цепочек итераторов. В некоторых случаях for_each также может быть быстрее, чем цикл, потому что он будет использовать внутреннюю итерацию на адаптерах Chain

method.for_each


fn main(){
    use std::sync::mpsc::channel;
    let (tx, rx) = channel();
    (0..5).map(|x| x * 2 + 1) .for_each(move |x| tx.send(x).unwrap());

    let v: Vec<_> =  rx.iter().collect();
    assert_eq!(v, vec![1, 3, 5, 7, 9]);

    (0..5).flat_map(|x| x * 100 .. x * 110)
      .enumerate()
      .filter(|&(i, x)| (i + x) % 3 == 0)
      .for_each(|(i, x)| println!("{}:{}", i, x));
}

inspect<F>(self, f: F) -> Inspect<Self, F> - в качестве инструмента отладки встраивания на различных участках конвейера итераторов

method.inspect


fn main(){
    let a = [1, 4, 2, 3];
    let sum = a.iter()
        .cloned()
        .inspect(|x| println!("about to filter: {}", x))
        .filter(|x| x % 2 == 0)
        .inspect(|x| println!("made it through filter: {}", x))
        .fold(0, |sum, i| sum + i);

     let lines = ["1", "2", "a"];
     let sum: i32 = lines
            .iter().map(|line| line.parse::())
            .inspect(|num| {
                if let Err(ref e) = *num { println!("Parsing error: {}", e);}
            })
            .filter_map(Result::ok).sum();
     println!("Sum: {}", sum);
}

all<F>(&mut self, f: F) -> bool - проверка соответствия всех элементов условию ф-цию Останавливается на первом false

any<F>(&mut self, f: F) -> bool - проверка наличия любого элемента который удовлетворяет ф-цию Останавливается на первом true

is_sorted(), is_sorted_by(), is_sorted_by_key() - Проверяет, отсортированы ли элементы этого итератора.


fn main(){
    let a = [1, 2, 3];
    assert!(a.iter().all(|&x| x > 0));
    assert!(!a.iter().all(|&x| x > 2));
}


fn main(){
    let a = [1, 2, 3];
    assert!(a.iter().any(|&x| x > 0));
    assert!(!a.iter().any(|&x| x > 5));
}


fn main(){
    #![feature(is_sorted)]
    assert!([1, 2, 2, 9].iter().is_sorted());
    assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
    assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
}

Адаптеры

  • map(( T) -> U) -> Iterator<Item = U> - преобразует значения итератора в другой вид
  • map_windows() - Преобразует данные функцией каждого непрерывного окна размером N
  • filter((&T) -> bool) -> Iterator<Item = T> - фильтрует ел. ф-ей предикатом
  • filter_map(( T) -> Option<U>) -> Iterator<Item = U> - фильтрует ел. ф-ей предикатом и преобразует
  • peekable(self) -> Peekable<Self> - Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора, не потребляя его.

Адаптеры итераторов - Функции, которые принимают Iterator и возвращают другой Iterator (форма паттерна «адаптер»)

Адаптеры итераторов получают итератор и изменяют его каким-то образом, выдавая новый итератор

Вы же не стали бы использовать filter_map, верно?


fn main(){
    let res = (1..=4).map(|x| x + 1);
    for x in res {
         println!("{}", x);// 2 3 4 5
    }
}


enum Status {
   Value(String),
   Stop,
}
fn main(){
    let list_of_numbers = vec![1, 2, 3];
    let list_of_strings1: Vec = list_of_numbers.iter().map(|i| i.to_string()).collect();
    let list_of_strings2: Vec = list_of_numbers.iter().map(ToString::to_string).collect();
    let list_of_strings2: Vec = list_of_numbers.iter().map(ToString::to_string).map(Status::Value).collect();
}


fn f(item:&i32)->String{
     format!("{item}")
}
fn main() {
      let f2 = |item:&i32|->String{
          format!("{item}")
      };
      let list_of_numbers = vec![1, 2, 3];
      let list_of_strings: Vec = list_of_numbers.iter().map(ToString::to_string).collect();
      let list_of_strings: Vec = list_of_numbers.iter().map(f).collect();
      let list_of_strings: Vec = list_of_numbers.iter().map(f2).collect();
}


enum Status {
   Value(u32),
   Stop,
}
fn main(){
    let list_of_statuses: Vec = (0u32..20).map(Status::Value).collect();
}


#![feature(iter_map_windows)] 
fn main(){
    let strings = "abcd".chars()
        .map_windows::<_,_,2>(|[x, y]| format!("{}+{}", x, y))
        .collect::>();
    assert_eq!(strings, vec!["a+b", "b+c", "c+d"]);
}


fn main(){
    for i in (1..10).filter(|&x| x % 2 == 0) {
         println!("{}", i);
    }
//Вы можете соединить все три понятия вместе: начать с итератора, адаптировать его несколько раз, а затем потребить результат
    (1..)
        .filter(|&x| x % 2 == 0)
        .filter(|&x| x % 3 == 0)
        .take(5)
        .collect::>();
}


// поиск значений 
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents.lines().filter(|line| line.contains(query)).collect()
}
fn main(){
  let v:Vec = (0..10).filter(|x| x % 2 == 0).chain(15..20).collect(); // //[0, 2, 4, 6, 8, 15, 16, 17, 18, 19]
// Поскольку замыкание, переданное в filter (), принимает ссылку, и многие итераторы перебирают ссылки, это приводит к возможной запутанной ситуации, когда тип замыкания является двойной ссылкой:
  let mut iter = [0, 1, 2].into_iter().filter(|x| **x > 1);
// Обычно вместо этого используется деструктурирование аргумента, чтобы отбросить его:
  let mut iter = [0, 1, 2].into_iter().filter(|&x| *x > 1);
// Или оба
  let mut iter = [0, 1, 2].into_iter().filter(|&&x| x > 1); 
}


fn main(){
    let mut iter = ["1", "lol", "3", "NaN", "5"].iter().filter_map(|s| s.parse().ok());
    assert_eq!(iter.next(), Some(1));assert_eq!(iter.next(), Some(3));assert_eq!(iter.next(), Some(5));
        
// Вот такой же пример но с filter and map (удобнее использовать чем  filter и map)
     let mut iter = ["1", "lol", "3", "NaN", "5"].iter().map(|s| s.parse()).filter(|s| s.is_ok()).map(|s| s.unwrap()); 
}


fn main(){
    let mut iter = [1, 2, 3].iter().peekable();
// peek() lets us see into the future
    assert_eq!(iter.peek(), Some(&&1));
    assert_eq!(iter.next(), Some(&1));
}

intersperse() - Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора. (для Clone)

intersperse_with() - как intersperse но для Copy


fn main(){
    #![feature(iter_intersperse)]
    let mut a = [0, 1, 2].iter().intersperse(&100);
    assert_eq!(a.next(), Some(&0));   // The first element from `a`.
    assert_eq!(a.next(), Some(&100)); // The separator.
    assert_eq!(a.next(), Some(&1));   // The next element from `a`.
    assert_eq!(a.next(), Some(&100)); // The separator.
}

Адаптеры

  • skip(usize) -> Iterator<Item = T> - Создает итератор, который пропускает первые n элементов.
  • take(usize) -> Iterator<Item = T> - Создает итератор, со следующими n элементами.
  • skip_while((&T) -> bool) -> Iterator<Item = T> - как skip() но решение принимает ф-ия предикат.
  • take_while((&T) -> bool) -> Iterator<Item = T> - как take() но при условии выполнения ф-ия предиката
  • map_while() - Создает итератор, который возвращает элементы на основе предиката и сопоставлений. Потребляет значения
  • step_by(usize) -> Iterator<Item = T> - Создает итератор с измененным шагом итерации
  • enumerate()->Iterator<Item=(usize, T)> - Создает итератор с текущее количество итераций и значением.
  • advance_by(usize)->Result<(), NonZeroUsize> - Перемещает итератор вперед по n элементам

Адаптеры итераторов - Функции, которые принимают Iterator и возвращают другой Iterator (форма паттерна «адаптер»)

Адаптеры итераторов получают итератор и изменяют его каким-то образом, выдавая новый итератор


fn main(){
    for i in (1..10).skip(1).take(5) {
            println!("{}", i);
    }
    //  бесконечный итератор  (1..)
    for i in (1..).take(5) {
       println!("{}", i);
    }
}


fn main(){
    let mut iter = [1, 2, 3].iter().skip(2);
    assert_eq!(iter.next(), Some(&3));
}


fn main(){
    let mut iter = [-1i32, 0, 1].into_iter().skip_while(|x| x.is_negative());
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    Поскольку замыкание, переданное в skip_while(), принимает ссылку
    let mut iter = [-1, 0, 1].into_iter().skip_while(|x| **x < 0); // need two *s!
    let mut iter = [-1, 0, 1].into_iter().skip_while(|&&x| x < 0); 
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    Упростить при деструкции
    let mut iter = a.into_iter().filter(|&x| *x < 0); 
    let mut iter = a.into_iter().filter(|&&x| x < 0);
}


fn main(){
// Обрывает итератор при первом false
    let mut iter = [1, 3, 2,4].into_iter();
    let result: Vec = iter.by_ref()
            .take_while(|&&n| n != 3)
            .cloned()
            .collect();
    println!("{:?}",result);// 1

    let mut iter = [-1i32, 0, 1].into_iter().take_while(|x| x.is_negative());
    assert_eq!(iter.next(), Some(&-1));
    assert_eq!(iter.next(), None);

    let mut iter = [-1, 0, 1];.into_iter().take_while(|&&x| x < 0); // need two *s!
    assert_eq!(iter.next(), Some(&-1));
    assert_eq!(iter.next(), None);
}


fn main(){
    let a = [1, 2, -3, 4];
    let mut iter = a.iter();
    let result: Vec = iter.by_ref().map_while(|n| u32::try_from(*n).ok()).collect();
    assert_eq!(result, &[1, 2]);
}


fn main(){
    let mut iter = [0, 1, 2, 3, 4, 5].iter().step_by(2);
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), Some(&4));
    assert_eq!(iter.next(), None);
}


fn main(){
    let vec = vec![1, 2, 3];
    for (index, v) in vec.iter().enumerate() {
       print!( "{} :{}", index,v);
    }

    другой тип индекса через zip
    for (count, v) in vec.iter().zip(0i32..) {
        print!( "{}:{} ", count,v);
    }
}


#![feature(iter_advance_by)]
fn main(){
    use std::num::NonZeroUsize;
    let a = [1, 2, 3, 4];
    let mut iter = a.iter();
    assert_eq!(iter.advance_by(2), Ok(()));  assert_eq!(iter.next(), Some(&3));  assert_eq!(iter.advance_by(0), Ok(()));
    assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&4` was skipped
}

Адаптеры

Combining with other iterators

  • chain(IntoIterator<Item = T>) -> Iterator<Item = T> - дописывает итератор в конец итератора
  • zip(IntoIterator<Item=U>)->Iterator<Item=(T,U)> - два итератора в один итератор пар соответствии позиции
  • array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> - Возвращает итератор по N элементам итератора одновременно
  • unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) - потребляет весь итератор пар, создавая две коллекции: одну из левых элементов пар и одну из правых элементов.
  • scan(S, (&mut S, T) -> Option<U>) -> Iterator<Item = U> - как fold но возвращает новый итератор
  • fuse(self) -> Fuse<Self> - Создает итератор, который заканчивается после первого [None]
fn main(){
    let v:Vec<i32> = (0..6).filter(|x| x % 2 == 0).chain(0..6).collect();
    assert_eq!(v,vec![0, 2, 4, 0, 1, 2, 3, 4, 5]);
}

fn main(){
    let names_ru = vec![String::from("привет"), String::from("пока")];
    let names_en = vec![String::from("hello"), String::from("bay")];
    let library:Vec<_> =  names_ru.iter().zip(names_en.iter()).collect();
    for i in library.iter(){
        let (ru,en) = i;// привет=hello пока=bay
    }
// после zip соединения двух итераторов в map можно брать оба итератора как a и b
// .... names_ru.iter().zip(names_en.iter()).map(|(iter_1,iter_2)|{....})
}

fn zipmap<F: Fn(&T) -> R, T, R>(xs: &[T], fs: &[F]) -> Vec<R> {
    let iter = xs.iter().zip(fs);
    let mut res = Vec::with_capacity(iter.len()); // ^^
    for (x, f) in iter {
         res.push(f(x));
    }
    res
}
fn main(){
  let lymda = |v:&i32|->i32 {
    v*10
  };
  let res =  zipmap(&[2,3,4],&[lymda,lymda,lymda]);
  assert_eq!([20, 30, 40],&res[..]);
}

// Здесь мы берем два среза и складываем числа вместе, помещая результат в третий срез. 
pub fn foo(a: &[u8], b: &[u8], res: &mut [u8]) {
    for ((a, b), res) in a.iter().zip(b).zip(res) { *res = *a + *b; }
}
fn main(){}

#![feature(iter_array_chunks)]
fn main(){
    let mut iter = "lorem".chars().array_chunks::<3>();
    assert_eq!(iter.next(), Some(['l', 'o','r']));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.into_remainder().unwrap().as_slice(), &['e','m']);
}

fn main(){
    let a = [(1, 2), (3, 4)];
    let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
    assert_eq!(left, [1, 3]);
    assert_eq!(right, [2, 4]);
}

fn main(){
    let init = 10;
    let mut total_iter = [1, 2, 3].iter().scan(init, |state, &x| {
        *state = *state * x;
        Some(*state)
    });
    for i in total_iter{
        print!("{}",i);// 10,20,60
    }
}

struct Alternate {
        state: i32,
}
impl Iterator for Alternate {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
            let val = self.state;
            self.state = self.state + 1;
            // if it's even, Some(i32), else None
            if val % 2 == 0 { Some(val) } else { None }
    }
}
fn main(){
    let mut iter = Alternate { state: 0 };
    assert_eq!(iter.next(), Some(0)); assert_eq!(iter.next(), None); assert_eq!(iter.next(), Some(2)); assert_eq!(iter.next(), None);

    let mut iter = iter.fuse();
    assert_eq!(iter.next(), Some(4));  assert_eq!(iter.next(), None);  assert_eq!(iter.next(), None);  assert_eq!(iter.next(), None); 
    assert_eq!(iter.next(), None);
}

Адаптеры Reversing and cycling

  • rev() -> Iterator<Item = T> - Изменяет направление итератора на обратное
  • cycle() -> Iterator<Item = T> where Self: Clone - Повторяет итератор бесконечно
  • cloned() -> Iterator<T> where T: Clone - Создает итератор, который клонирует все его элементы ссылки
  • copied() -> Iterator<T> where T: Copy - Создает итератор, который копирует все его элементы. Это полезно, когда у вас есть итератор над &T, но вам нужен итератор над T.
  • by_ref(&mut self) -> &mut Self - Заимствует итератор, а не потребляет его. Это полезно, чтобы разрешить применение адаптеров итератора при сохранении права собственности на исходный итератор.

method.copied


fn main(){
    let a = [1, 2];
    let mut iter = a.iter().rev();
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), None);
}


fn main(){
    let a = [1, 2];
    let mut it = a.iter().cycle();

    assert_eq!(it.next(), Some(&1));
    assert_eq!(it.next(), Some(&2));
    assert_eq!(it.next(), Some(&1));
    assert_eq!(it.next(), Some(&2));
    assert_eq!(it.next(), Some(&1));
}


fn main(){
    let a = [1, 2, 3];
    let v_cloned: Vec<_> = a.iter().cloned().collect();
    // cloned is the same as .map(|&x| x), for integers
    let v_map: Vec<_> = a.iter().map(|&x| x).collect();

    assert_eq!(v_cloned, vec![1, 2, 3]);
    assert_eq!(v_map, vec![1, 2, 3]);
}


fn main(){
    let a = [1, 2, 3];
    let v_copied: Vec<_> = a.iter().copied().collect();
    let v_map: Vec<_> = a.iter().map(|&x| x).collect();

    assert_eq!(v_copied, vec![1, 2, 3]);
    assert_eq!(v_map, vec![1, 2, 3]);
}


fn main(){
    let a = [1, 2, 3,4,5];
    let mut iter = a.into_iter();
    // take вырезал первых три элемента
    let sum: i32 = iter.by_ref().take(3).fold(0, |acc, i| acc + i );
    assert_eq!(sum, 6);
    // используем дальше итератор, при условии что он не дошел до конца
    for i in iter{
       print!("{}/",i);
    }
}

Адаптеры

flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> - Создает итератор, который работает как map, но выравнивает вложенную структуру

Замыкание map возвращает один элемент для каждого элемента, а Замыкание flat_map() возвращает итератор для каждого элемента. Превращает элемент в последовательность

flatten(self) -> Flatten<Self> - Создает итератор, выравнивающий вложенную структуру. (хотите удалить один уровень косвенности)

method.flatten

method.fuse


fn main(){
    let words = ["alpha", "beta", "gamma"];
    // chars() returns an iterator
    let merged: String = words.iter()
                                      .flat_map(|s| s.chars())
                                      .collect();
    assert_eq!(merged, "alphabetagamma");

    // Через map
      let words = ["alpha", "beta", "gamma"];
      // chars() returns an iterator
      let merged: String = words.iter().map(|s| s.chars()).flatten().collect();
}


fn main(){
// Вывести по стране ее города:
    use std::collections::HashMap;
    let mut major_cities = HashMap::new();
    major_cities.insert("Japan", vec!["Tokyo", "Kyoto"]);
    major_cities.insert("The United States", vec!["Portland", "Nashville"]);
    major_cities.insert("Brazil", vec!["São Paulo", "Brasília"]);
    major_cities.insert("Kenya", vec!["Nairobi", "Mombasa"]);
    major_cities.insert("The Netherlands", vec!["Amsterdam", "Utrecht"]);
    let countries = ["Japan", "Brazil", "Kenya"];
    for &city in countries.iter().flat_map(|country| &major_cities[country]) {
         println!("{}", city);
    }
}


fn main(){
// Пифагоровы Тройки
    let triplets = (1u32..)
        .flat_map(|z| (1..=z).map(move |y| (y, z)))
        .flat_map(|(y, z)| (1..=y).map(move |x| (x, y, z)))
        .filter(|(x, y, z)| x*x + y*y == z*z);

    let first_ten: Vec<(u32, u32, u32)> = triplets.take(10).collect();

    // [(3, 4, 5), (6, 8, 10) ... (20, 21, 29)]
    println!("{}", first_ten)
/*
    map : трансформирует элементы последовательности
    flat_map : превращает элемент в последовательность
    filter , take , ...
    collect превращает "ленивый" итератор в коллекцию
*/
}

Адаптер со свойствами Потребителя

collect_into() - Собирает все элементы итератора в коллекцию.

Этот метод удобен для вызова Extend::extend , но вместо того, чтобы вызывать его для коллекции, он вызывается для итератора.

partition_in_place() - Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом. Возвращает количество true элементов.

method.collect_into


#![feature(iter_collect_into)]
fn main(){
    let a = [1, 2, 3];
    let mut vec: Vec:: = vec![0, 1];

    a.iter().map(|&x| x * 2).collect_into(&mut vec);
    a.iter().map(|&x| x * 10).collect_into(&mut vec);

    assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]);

    let a = [1, 2, 3];
    let mut vec: Vec:: = vec![0, 1];
    vec.extend(a.iter().map(|&x| x * 2));
    vec.extend(a.iter().map(|&x| x * 10));
    assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]);
}


#![feature(iter_partition_in_place)]
fn main(){
    let mut a = [1, 2, 3, 4, 5, 6, 7];
    let c = a.iter_mut().partition_in_place(|&n| n % 2 == 0);   
    assert_eq!(c,3);
    for i in a.iter().take(c){ assert!(i % 2 == 0);}
    for i in a.iter().skip(c){ assert!(i % 2 != 0);}
}

Потребители

collect() -> B where B: FromIterator<T> - Преобразует все значения итератора в коллекцию

Trait std::iter::Extend

Потребители - применяются к итератору, выдают некоторый конечный набор значений.

perf-book/iterators

method.find_map


fn main(){
    let one_to_one_hundred = (1..101).collect::>(); 
    let one_to_one_hundred = (1..101).collect::>();
    let one_to_one_hundred: Vec = (0..10).collect();
    let hash = s.chars().zip(s.chars().rev()).collect::>();
}


fn main(){
// collect преобразует итератор в коллекцию, требует выделения в куче. 
// Вам следует избегать вызова, collect если затем коллекция повторяется снова.
// По этой причине часто лучше возвращать тип итератора, например, `impl Iterator` из функции, чем из `Vec`

    struct A(Vec);
    impl<'a> A{
        fn get_item(&self) -> Vec {
               self.0.clone()
        }
        fn get_item_2(&'a self) -> impl Iterator +'a   {
               self.0.iter()
        }
    }
    let a = A(vec![1,2,3]);
    let res:Vec = a.get_item().into_iter().filter(|item| *item > 1).collect();

    let a = A(vec![1,2,3]);
    let res:Vec = a.get_item_2().filter(|item| *item > &1).cloned().collect();

    // Точно так же вы можете использовать extend для расширения существующей коллекции 
    // вместо того, чтобы выделяя память в куче collect 
    let mut msg = String::from("abc");
    let msg_extend: Vec = ['d', 'e', 'f'].iter().map(|c|(*c).try_into()).filter_map(Result::ok).collect(); ❌ 
    msg.push_str(String::from_utf8(msg_extend).expect("unicode character not in u8 range").as_str());
    assert_eq!("abcdef", &msg);

    let mut msg = String::from("abc");
    let iter_extend = ['d', 'e', 'f'].iter();
    msg.extend(iter_extend); ✅  // Расширьте коллекцию содержимым итератора. 
    assert_eq!("abcdef", &msg);
}


fn main(){
 let processed = things
    .filter_map(|t| ...)
    .map(|t| ...?; ...; Ok(u))
    .take(42)
    .collect::,io::Error>()?;
}

Потребители

try_collect() - Преобразует все Some/Ok/ControlFlow::Continue значения итератора в коллекцию до None/Err или после

method.try_collect


#![feature(iterator_try_collect)]
fn main(){
    let mut iter = [Some(1), Some(2), None, Some(3), Some(4)].into_iter();
    let v = iter.try_collect::>();
    assert_eq!(v, None);
    let v = iter.try_collect::>();
    assert_eq!(v, Some(vec![3, 4]));
}

Потребители

  • fold(S, (S, T) -> S) -> S - Получить одно значение на основе ф-ии предиката обработки итератора
  • try_fold<B, F, R>(&mut self, init: B, f: F) -> R - как fold() но возвращает Option/Result
  • partition((&T) -> bool) -> (B, B) where B: Default + Extend<T> - Создает две коллекции из итератора

Потребители - применяются к итератору, выдают некоторый конечный набор значений.


fn main(){
    //На каждой итерации вызывается замыкание, результат выполнения которого становится значением accumulator на следующей итерации.
    fold(base, |accumulator, element| ...)
      base - это элемент, называемый базой;
      |accumulator, element| — accumulator - сумма результатов каждой итерации, element - текущее значение.
        
    let init = 10;
    let mut total:i32 = [1, 2, 3].iter().fold(init, |mut state, &x| {
        state = state * x;
        state
    });
    assert_eq!(total,60);
}


fn main(){
    let init = 10;
    let mut total:i32 = [1, 2, 3].iter().try_fold(init, |mut state, &x| {
        state = state * x;
        if state < 60{
           return Some(state);// или Ok(state) 
        }
        None
    }).expect("msg non value");
    assert_eq!(total,60);
}


fn main(){
    let a = [1, 2, 3];
    let (even, odd): (Vec, Vec) = a
            .into_iter()
            .partition(|&n| n % 2 == 0);
    assert_eq!(even, vec![2]);
    assert_eq!(odd, vec![1, 3]);
}

Потребители

  • find((&T) -> bool) -> Option<T> - возвращает первый элемент удовлетворивший условие замыкания
  • try_find() - Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку
  • find_map((T) -> Option<U>) -> Option<U> - возвращает первый элемент с результатом Some
  • position((T) -> bool) -> Option<usize> - Ищет элемент в итераторе, возвращая его индекс.
  • rposition((T) -> bool) -> Option<usize> - как position но начинает с конца
  • last(self) -> Option<Self::Item> - Расходует итератор, возвращая последний элемент.
  • count() -> usize - Расходует итератор, подсчитывает количество итераций и возвращает его
  • sum<S>(self) -> S - Суммирует элементы итератора Может паниковать
  • product()-> P where P: Product<T> - умножение всех элементов на предыдущий результат
  • nth(&mut self, n: usize) -> Option<Self::Item> - Возвращает n-й элемент итератора. Забирает элемент

Потребители - применяются к итератору, выдают некоторый конечный набор значений.


fn main(){
    let a = [1, 2, 3];
    assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
    assert_eq!(a.iter().find_map(|&x| if x == 2{Some(x)}else{None}), Some(2)); 

    let first_number = ["lol", "NaN", "2", "5"].iter().find_map(|s| s.parse().ok());
    assert_eq!(first_number, Some(2));

}


fn main(){
    #![feature(try_find)]
    let a = ["1", "2", "lol", "NaN", "5"];
    let is_my_num = |s: &str, search: i32| -> Result {
        Ok(s.parse::()?  == search)
    };
    let result = a.iter().try_find(|&&s| is_my_num(s, 2));
    assert_eq!(result, Ok(Some(&"2")));
}


fn main(){
    let a = [1, 4, 4,3];
    assert_eq!(a.iter().position(|&x| x == 4), Some(1));
    assert_eq!(a.iter().rposition(|&x| x == 4), Some(2));
}


fn main(){
    "привет".char_indices().count() 6
    "привет".bytes().count() 12
    "МИР\tТРУД МАЙ".split_whitespace().count() 3
}


fn main(){
    let c:Option<(usize, char)> = "привет".char_indices().last();
    assert_eq!(c,Some((10, 'т')));

    let c:Option = "привет".bytes().last();
    assert_eq!(c,Some(130));

    let c:Option<&str> = "МИР\tТРУД МАЙ".split_whitespace().last();
    assert_eq!(c,Some("МАЙ"));
}


fn main(){
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    let total: i32 = v1_iter.sum();
    assert_eq!(total, 6);
// -----------------------------------------
    (1..).take_while(|&i| i <= n).sum()
}


fn factorial(n: u32) -> u32 {
     (1..).take_while(|&i| i <= n).product()
}
fn main(){
    assert_eq!(factorial(0), 1);
    assert_eq!(factorial(1), 1);
    println!("{}",factorial(5));//1*1=1 1*2=2 2*3=6 6*4=24 24*5=120
}


fn main(){
    let mut iter4 = "111 222 333".split(' ');
    assert_eq!(Some("222"),iter4.nth(1));
    assert_eq!(Some("333"),iter4.nth(0));
    assert_eq!(None,iter4.nth(0));
}

Потребители

try_for_each<F, R>(&mut self, f: F) -> R - продолжает перебор до первого Err результата и вернет его


use std::ops::ControlFlow;
fn main(){
    let r = (2..100).try_for_each(|x| {
        if 323 % x == 0 {
            return ControlFlow::Break(x)
        }
        ControlFlow::Continue(())
    });
    assert_eq!(r, ControlFlow::Break(17));
}

use std::io::{stdout, Write,Error, ErrorKind};
fn main(){
    let data = [1, 2, 3,4];
    let res = data.iter().try_for_each(|&x|
        if x <= 2 {
            writeln!(stdout(), "{}", x);
           Ok(())
        }else{
            Err(Error::new(ErrorKind::Other,  format!("{}", format_args!("Error pop {}", x))))
        }
    );
    match res {
        Err(e) => println!("{}",e),// Error pop 3
        _ => println!("")
    }
}

Потребители

next_chunk() - Перемещает итератор и возвращает массив, содержащий следующие N значения


#![feature(iter_next_chunk)]
fn main(){
    let quote = "not all those who wander are lost";
    let [first, second, third] = quote.split_whitespace().next_chunk::<3>().unwrap();
    assert_eq!(first, "not");
    assert_eq!(second, "all");
}

Потребители Maximum and minimum

  • max() -> Option<T> - Возвращает максимальный элемент итератора.
  • min() -> Option<T> - Возвращает минимальный элемент итератора.
  • max_by((&T, &T) -> Ordering) -> Option<T> - элемент давший максимальное значение из функции
  • min_by((&T, &T) -> Ordering) -> Option<T> - элемент давший минимальное значение из функции
  • max_by_key((&T)->U) ->Option<T> - элемент давший максимальное значение из функции
  • min_by_key((&T)->U) ->Option<T> - элемент давший минимальное значение из функции
  • size_hint(&self) -> (usize, Option<usize>) - Возвращает границы (min, max) на оставшейся длине итератор
  • reduce<F>(self, f: F) -> Option<Self::Item> - Сводит итератор к одному значению
  • try_reduce() - Уменьшает элементы до одного, многократно применяя операцию сокращения.

Потребители - применяются к итератору, выдают некоторый конечный набор значений.

enum.Ordering


fn main(){
    let a = [1, 2, 3];
    let b: Vec = Vec::new();
    assert_eq!(a.iter().max(), Some(&3));
    assert_eq!(b.iter().max(), None
}


fn main(){
    let a = [1, 2, 3];
    let b: Vec = Vec::new();
    assert_eq!(a.iter().min(), Some(&1));
    assert_eq!(b.iter().min(), None);
}


fn main(){
    let a = [-3_i32, 0, 1, 5, -10];
    assert_eq!(*a.iter().max_by_key(|x| x.abs()).unwrap(), -10);
    assert_eq!(*a.iter().max_by_key(|x| *x>&1).unwrap(), 5);
}


fn main(){
   let a = [-3_i32, 0, 1, 5, -10];
    assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
}


fn main(){
    let a = [10, 20, 30,40,50];
    let iter = a.iter();
    assert_eq!((5, Some(5)), iter.size_hint())
//---------------------------------------------------------
    let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20);

    // now both bounds are increased by five
    assert_eq!((5, Some(15)), iter.size_hint());
}


fn main(){
    let a = [10, 20, 5, -23 ,21,0];
    let b: [u32; 0] = [];
    assert_eq!(a.iter().reduce(|a, b| {
            if a >= b { a } else { b }
    }), Some(&20));
        
    assert_eq!(b.iter().reduce(|a, b| {
            if a >= b { a } else { b }
    }), None);
}


fn main(){
    Безопасно вычислите сумму ряда чисел
    #![feature(iterator_try_reduce)]

    let numbers: Vec = vec![10, 20, 5, 23, 0];
    let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
    assert_eq!(sum, Some(Some(58)));
}

Функции:

  • from_generator() - Создает новый итератор, где каждая итерация вызывает предоставленный генератор.
  • empty() - Создает итератор, который ничего не дает.
  • from_fn() - Создает новый итератор, где каждая итерация вызывает предоставленное замыкание F: FnMut() -> Option<T>.
  • once( )- Создает итератор, который возвращает элемент ровно один раз.
  • once_with() - Создает итератор, который лениво генерирует значение ровно один раз, вызывая предоставленное закрытие.
  • repeat() - Создает новый итератор, который бесконечно повторяет один элемент.
  • repeat_with() - Создает новый итератор, который бесконечно повторяет элементы типа, применяя предоставленное замыкание, повторитель, F: FnMut() -> A.
  • successors() - Создает новый итератор, в котором каждый последующий элемент вычисляется на основе предыдущего.
  • zip() - Преобразует аргументы в итераторы и архивирует их.

Function std::iter::empty

fn.empty


use std::iter;
fn main(){
    // это мог бы быть итератор по i32, но увы, это не так.
    let mut nope = iter::empty::();
    assert_eq!(None, nope.next());
}

Function std::iter::once

iter/fn.once

Соединение вместе с другим итератором. Предположим, что мы хотим перебирать каждый файл .foo каталога, но также файл конфигурации .foorc: Создает итератор, который дает элемент ровно один раз. Это обычно используется для адаптации одного значения к chain другим видам итераций.


use std::iter;
use std::fs;
use std::path::PathBuf;
fn main(){
    let dirs = fs::read_dir(".foo").unwrap();
    let dirs = dirs.map(|file| file.unwrap().path());
    let config = iter::once(PathBuf::from(".foorc"));

// свяжите два итератора вместе в один большой итератор 
    let files = dirs.chain(config);

//  это даст нам все файлы в .foo, а также .foorc для  .foorc в файлах  
    for f in files {
        println!("{:?}", f);
    }
}


use std::iter;
use std::fs;
use std::path::PathBuf;
fn main(){
    let dirs = fs::read_dir(".foo").unwrap();

    // нам нужно преобразовать итератор DirEntry-s в итератор 
    // PathBufs, поэтому мы используем map
    let dirs = dirs.map(|file| file.unwrap().path());

    // теперь наш итератор только для нашего конфигурационного файла
    let config = iter::once(PathBuf::from(".foorc"));

    // объединить два итератора в один большой итератор
    let files = dirs.chain(config);

    // это даст нам все файлы в .foo, а также .foorc
    for f in files {
        println!("{:?}", f);
    }
}

Function std::iter::repeat()

Function std::iter::repeat_with()

iter/fn.repeat

Создает новый итератор, который бесконечно повторяет один элемент.

Если тип элемента итератора, который вам нужен, не реализует Clone, или если вы не хотите сохранять повторяющийся элемент в памяти, вы можете вместо этого использовать функцию repeat_with.

use std::iter;
fn main(){
    let mut fours = iter::repeat(4);

    assert_eq!(Some(4), fours.next());
    assert_eq!(Some(4), fours.next());
    assert_eq!(Some(4), fours.next());
    assert_eq!(Some(4), fours.next());
    assert_eq!(Some(4), fours.next());

    // да, все еще четыре
    assert_eq!(Some(4), fours.next());
//-------------------------------------------
    let mut fours = iter::repeat(4).take(1);
    assert_eq!(Some(4), fours.next());
    // .. и теперь мы закончили
    assert_eq!(None, fours.next());
}

fn random(n: usize) -> Vec<u32> {
    let mut r = 92;
    std::iter::repeat_with(move || {
        r ^= r << 13;
        r ^= r >> 17;
        r ^= r << 5;
        r
    }).take(n).collect()
}
fn main() {
    let n: usize = 3;
    let indexes: Vec<usize> = (0..n).collect();
    let xs: Vec<u32> = random(n);
    println!("{:?}",xs);// [24873849, 1921449235, 163429281]
}

Function std::iter::from_fn

Создает новый итератор, где каждая итерация вызывает предоставленное закрытие F: FnMut() -> Option<T>


fn main(){
    let mut count = 0;
    let counter = std::iter::from_fn(move || {
        // Увеличиваем счёт. Вот почему мы начали с нуля.
        count += 1;

        // Проверьте, закончили ли мы подсчет или нет.
        if count < 6 {
            Some(count)
        } else {
            None
        }
    });
    assert_eq!(counter.collect::>(), &[1, 2, 3, 4, 5]);
}

Function std::iter::successors

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               `fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F> where  F:FnMut(&T) -> Option<T>`

Создает новый итератор, в котором каждый последующий элемент вычисляется на основе предыдущего.


use std::iter::successors;
fn main(){
    let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
    assert_eq!(powers_of_10.collect::>(), &[1, 10, 100, 1_000, 10_000]);


    let res = successors(Some(1_u32),|v|{ 
        if *v < 5 {
            Some(v+1)
        }
        else{ None }
    });
    assert_eq!(res.collect::>(), &[1, 2, 3, 4, 5]);

    let f = |v:&u32|{
        if *v < 5 {
            Some(v+1)
        }
        else{ None }
    };

    let res =  successors(Some(1_u32),f);
    assert_eq!(res.collect::>(), &[1, 2, 3, 4, 5]);
}

Существует несколько вариаций метода zip, которые позволяют объединять два итератора в один, создавая кортежи из соответствующих элементов.

Это позволяет легко обрабатывать данные, поступающие из разных источников, одновременно


use std::iter::zip;
fn main(){
    let xs = [1, 2, 3];
    let ys = [4, 5, 6];
    let mut iter = zip(xs, ys);
    assert_eq!(iter.next().unwrap(), (1, 4));
    assert_eq!(iter.next().unwrap(), (2, 5));
}

rayon = "1.0.2"

Район является библиотекой параллелизма данных для Rust.

Он чрезвычайно легкий и облегчает преобразование последовательного вычисления в параллельное.

par_iter() или par_iter_mut(), into_par_iter()

  • for_each
  • for_each_with
  • try_for_each
  • try_for_each_with
  • count
  • map - map_op к каждому элементу этого итератора, создавая новый итератор
  • map_with
  • cloned - Создает итератор, который клонирует все его элементы.&T -> T.
  • inspect - для отладки, чтобы увидеть, что происходит на этапах итератора.
  • update - Мутация каждого элемента этого итератора перед его уступкой
  • filter - Фильтрует элементы итератора
  • filter_map
  • flat_map
  • flatten - Адаптер, который сглаживает итерируемые Items в один большой итератор
  • reduce
  • reduce_with
  • try_reduce
  • try_reduce_with
  • fold
  • fold_with
  • try_fold
  • try_fold_with
  • sum
  • product - Умножает все элементы в итераторе
  • min
  • min_by
  • min_by_key
  • max
  • max_by
  • max_by_key
  • chain - Принимает два итератора и создает новый итератор для обоих.
  • find_any - Ищет элемент по предикату и возвращает его
  • find_first
  • find_last
  • any
  • all
  • while_some
  • collect
  • unzip - Распаковывает элементы параллельного итератора в пару контейнеров
  • partition - Разделяет элементы параллельного итератора на пару контейнеров
  • partition_map
  • intersperse - Перемещает клоны элемента между элементами этого итератора.
  • opt_len

fn main(){
// for_each
// два потока всего выделяет ?
    (1..6).into_par_iter().for_each(|x| { if x%2==0 {std::thread::sleep( std::time::Duration::new(2, 00000000));} println!("{:?}", x) });
}


fn main(){
// for_each_with
    //initЗначение будет клонирован только по мере необходимости , чтобы быть в паре с группой элементов в каждом районе работы. Для этого не требуется тип Sync.
    let (sender, receiver) = channel();
    (1..6).into_par_iter().for_each_with(sender, |s, x|{ s.send(x).unwrap()} );
    let mut res: Vec<_> = receiver.iter().collect();
    res.sort();
   // assert_eq!(&res[..], &[0, 1, 2, 3, 4])
    println!("{:?}", res)
}


fn main(){
// try_for_each - Выполняет OP параллельную попытку для каждого элемента, созданного итератором.
       use std::io::Write;
        (0..10).into_par_iter()
        .try_for_each(|x| {writeln!(std::io::stdout(), "{:?}", x)})
        .expect("expected no write errors");
}


fn main(){
// try_for_each_with - Выполняет параллельную ошибку OPс заданным initзначением с каждым элементом, созданным итератором.
// Это объединяет initсемантику for_each_with()и семантику отказа try_for_each()
    let (sender, receiver) = channel();
    (0..5).into_par_iter()
        .try_for_each_with(sender, |s, x| s.send(x))
        .expect("expected no send errors");
    let mut res: Vec<_> = receiver.iter().collect();
    res.sort();
    assert_eq!(&res[..], &[0, 1, 2, 3, 4]);
}


fn main(){
// count - Подсчитывает количество элементов в этом параллельном итераторе.
    let count = (0..100).into_par_iter().count();
    assert_eq!(count, 100);
}


fn main(){
// map - Применяется map_op к каждому элементу этого итератора, создавая новый итератор с результатами
    let mut par_iter = (0..5).into_par_iter().map(|x| x * 2);
    let doubles: Vec<_> = par_iter.collect();
    assert_eq!(&doubles[..], &[0, 2, 4, 6, 8]);
}


fn main(){
// cloned - Создает итератор, который клонирует все его элементы. Это может быть полезно, когда у вас есть итератор &T, но вам нужно T.
    let a = [1, 2, 3];
    let v_cloned: Vec<_> = a.par_iter().cloned().collect();
    let v_map: Vec<_> = a.par_iter().map(|&x| x).collect();
    assert_eq!(v_cloned, vec![1, 2, 3]);
    assert_eq!(v_map, vec![1, 2, 3]);
}

map_with


fn main(){
    // map_with - Применяется map_op к данному init значению с каждым элементом этого итератора, создавая новый итератор с результатами.
    // init Значение будет клонирован только по мере необходимости , чтобы быть в паре с группой элементов в каждом районе работы. Для этого не требуется тип Sync
    let (sender, receiver) = channel();
    let a: Vec<_> = (0..5)
        .into_par_iter()
        .map_with(sender, |s, x:i32| {
            s.send(x).unwrap();     // sending i32 values through the channel
            x                       // returning i32
        })
        .collect();
    let mut b: Vec<_> = receiver.iter()         // iterating over the values in the channel
        .collect();     // and collecting them
    b.sort();
    assert_eq!(a, b);
}
  • inspect
  • update
  • filter

fn main(){
// inspect - Применяется inspect_op к ссылке на каждый элемент этого итератора, создавая новый итератор, проходящий через исходные элементы.
// Это часто полезно для отладки, чтобы увидеть, что происходит на этапах итератора.
    let a = [1, 4, 2, 3];
    let sum = a.par_iter()
        .cloned()
        .inspect(|x| println!("about to filter: {}", x))
        .filter(|&x| x % 2 == 0)
        .inspect(|x| println!("made it through filter: {}", x))
        .reduce(|| 0, |sum, i| sum + i);
    println!("{}", sum);
}


fn main(){
 // update Мутация каждого элемента этого итератора перед его уступкой.
    let par_iter = (0..5).into_par_iter().update(|x| {*x *= 2;});
    let doubles: Vec<_> = par_iter.collect();
    assert_eq!(&doubles[..], &[0, 2, 4, 6, 8]);

    let mut a = [1, 4, 2, 3];
    let par_iter = a.par_iter().update(|mut x| {*x *= 2;});
}


fn main(){
// filter - Применяется filter_op к каждому элементу этого итератора, создавая новый итератор только с элементами, которые дали true результаты.
    let mut par_iter = (0..10).into_par_iter().filter(|x| x % 2 == 0);
    let even_numbers: Vec<_> = par_iter.collect();
    assert_eq!(&even_numbers[..], &[0, 2, 4, 6, 8]);
}
  • filter_op
  • map_op
  • flatten

fn main(){
//Применяется filter_op к каждому элементу этого итератора для получения Option, создавая новый итератор только с элементами из Some результатов
    let mut par_iter = (0..10).into_par_iter()
        .filter_map(|x| {
            if x % 2 == 0 { Some(x * 3) }
                else { None }
        });
    let even_numbers: Vec<_> = par_iter.collect();
    assert_eq!(&even_numbers[..], &[0, 6, 12, 18, 24]);
}


fn main(){
    // Применяется map_op к каждому элементу этого итератора, чтобы получить вложенные итераторы, создавая новый итератор, который выравнивает их обратно в один.
    // to_vec() Срез копирует себя в Vec
    let a = [[1, 2], [3, 4], [5, 6], [7, 8]];
    let par_iter = a.par_iter().cloned().flat_map(|a| a.to_vec());
    let vec: Vec<_> = par_iter.collect();
    assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8]);
}


fn main(){
 // flatten Адаптер, который сглаживает итерируемые Items в один большой итератор.
    // как flat_map только работает с векторами
    let x: Vec> = vec![vec![1, 2], vec![3, 4]];
    let y: Vec<_> = x.into_par_iter().flatten().collect();
    assert_eq!(y, vec![1, 2, 3, 4]);
}
  • reduce
  • reduce_with
  • try_reduce_with

fn main(){
    // reduce
    let sums:(i32,i32) = [(0, 1), (5, 6), (16, 2), (8, 9)]
        .par_iter()        // iterating over &(i32, i32)
        .cloned()          // iterating over (i32, i32)
        .reduce(|| (0, 0), // the "identity" is 0 in both columns
                |a:(i32,i32), b:(i32,i32)| (a.0 + b.0, a.1 + b.1));
    assert_eq!(sums, (0 + 5 + 16 + 8, 1 + 6 + 2 + 9));
}


fn main(){
   // reduce_with
    let sums = [(0, 1), (5, 6), (16, 2), (8, 9)]
        .par_iter()        // iterating over &(i32, i32)
        .cloned()          // iterating over (i32, i32)
        .reduce_with(|a, b| (a.0 + b.0, a.1 + b.1))
        .unwrap();
    assert_eq!(sums, (0 + 5 + 16 + 8, 1 + 6 + 2 + 9));
}


fn main(){
// try_reduce_with
    let files = ["/dev/null", "/does/not/exist"];
    files.into_par_iter()
        .map(|path| std::fs::metadata(path).map(|m| (path, m.len())))
        .try_reduce_with(|a, b| {
            Ok(if a.1 >= b.1 { a } else { b })
        })
        .expect("Some value, since the iterator is not empty")
        .expect_err("not found");
}
  • fold
  • fold_with
  • try_fold

fn main(){
// fold аналогично последовательному fold но работает паралельно разбывая на несколько блоков и потом их складывая
    let s =
        ['a', 'b', 'c', 'd', 'e']
            .par_iter()
            .fold(|| {String::new()},
                  |mut s: String, c: &char| { s.push(*c); s })
            .reduce(||{String::new()} ,
                    |mut a: String, b: String| { a.push_str(&b); a });
    assert_eq!(s, "abcde");

    let bytes = 0..22_u8;
    let sum = bytes.into_par_iter()
        .fold(|| 0_u32, |a: u32, b: u8| a + (b as u32))
        .sum::();
    assert_eq!(sum, (0..22).sum());
}


fn main(){
// fold_with - Это работает, по сути, как fold(|| init.clone(), fold_op), за исключением того, что не требуется init тип типа Sync, или любая другая форма добавленной синхронизации.
    let bytes = 0..22_u8;
    let sum = bytes.into_par_iter()
        .fold_with(0_u32, |a: u32, b: u8| a + (b as u32))
        .sum::();
    assert_eq!(sum, (0..22).sum());
}


fn main(){
// try_fold - Это вариант fold() для операций, которые могут завершиться с ошибкой  Option::Noneили Result::Err.
    let bytes = 0..22_u8;
    let sum = bytes.into_par_iter()
        .try_fold(|| 0_u32, |a: u32, b: u8| a.checked_add(b as u32))
        .try_reduce(|| 0, u32::checked_add);
    assert_eq!(sum, Some((0..22).sum()));
}
  • try_fold_with
  • sum
  • min, max

fn main(){
// try_fold_with Выполните ложную параллельную складку с клонируемым init значением.
//Это объединяет init семантику fold_with() и семантику отказа try_fold()
    let bytes = 0..22_u8;
    let sum = bytes.into_par_iter()
        .try_fold_with(0_u32, |a: u32, b: u8| a.checked_add(b as u32))
        .try_reduce(|| 0, u32::checked_add);
    assert_eq!(sum, Some((0..22).sum()));
}


fn main(){
// sum
    let a = [1, 5, 7];
    let sum: i32 = a.par_iter().sum();
    assert_eq!(sum, 13);

    //product Умножает все элементы в итераторе.
    fn factorial(n: u32) -> u32 {
        (1..n+1).into_par_iter().product()
    }
    assert_eq!(factorial(0), 1);
    assert_eq!(factorial(1), 1);
    assert_eq!(factorial(5), 120);
}


fn main(){
// min() max()
    let a = [-3_i32, 34, 2, 5, -10, -3, -23];
    assert_eq!(a.par_iter().min(), Some(&-23));
    assert_eq!(a.par_iter().min_by(|x, y| x.cmp(y)), Some(&-23));
    assert_eq!(a.par_iter().min_by_key(|x| x.abs()), Some(&2));
    assert_eq!(a.par_iter().max(), Some(&34));
    assert_eq!(a.par_iter().max_by(|x, y| x.abs().cmp(&y.abs())), Some(&34));
    assert_eq!(a.par_iter().max_by_key(|x| x.abs()), Some(&34));
}
  • chain
  • find_any, find_last, find_first
  • any

fn main(){
// chain - Принимает два итератора и создает новый итератор для обоих.
    let a = [0, 1, 2];
    let b = [9, 8, 7];
    let par_iter = a.par_iter().chain(b.par_iter());
    let chained: Vec<_> = par_iter.cloned().collect();
    assert_eq!(&chained[..], &[0, 1, 2, 9, 8, 7]);
}


fn main(){
// find_any Ищет какой-то элемент в параллельном итераторе, который соответствует данному предикату и возвращает его.
//  find_last find_first
    let a = [1, 2, 3, 3];
    assert_eq!(a.par_iter().find_any(|&&x| x == 3), Some(&3));
    assert_eq!(a.par_iter().find_any(|&&x| x == 100), None);
}


fn main(){
// any()->bool Ищет какой-то элемент в параллельном итераторе, который соответствует заданному предикату, и если так возвращает true.
    let a = [0, 12, 3, 4, 0, 23, 0];
    let is_valid = a.par_iter().any(|&x| x > 10 && x < 20 );
    assert!(is_valid);
}


fn main(){
// all->bool  Проверяет, что каждый элемент в параллельном итераторе соответствует заданному предикату, и если это так возвращает true
    let a = [0, 12, 3, 4, 0, 23, 0];
    let is_valid = a.par_iter().all(|&x| x > 10);
    assert!(!is_valid);
}
  • collect
  • unzip_into_vecs

collect - Создайте новую коллекцию, содержащую весь элемент, созданный этим параллельным итератором. Вы можете предпочесть использовать collect_into_vec(), который более эффективно распределяется с точным знанием того, сколько элементов содержит итератор, и даже позволяет повторно использовать хранилище существующего вектора, а не выделять свежий вектор.


fn main(){
    let sync_vec: Vec<_> = (0..100).into_iter().collect();
    let async_vec: Vec<_> = (0..100).into_par_iter().collect();
    assert_eq!(sync_vec, async_vec);

    let mut vec: Vec<_> = vec![];
    (0..100).into_par_iter().collect_into_vec(&mut vec);
}

Распаковывает элементы параллельного итератора в пару произвольных ParallelExtend контейнеров. Вы можете предпочесть использовать unzip_into_vecs(), который более эффективно распределяется с точным знанием того, сколько элементов содержит итератор, и даже позволяет повторно использовать резервные хранилища существующих векторов, а не выделять свежие векторы.


fn main(){
    let a = [(0, 1), (1, 2), (2, 3), (3, 4)];
    let (left, right): (Vec<_>, Vec<_>) = a.par_iter().cloned().unzip();
    assert_eq!(left, [0, 1, 2, 3]);
    assert_eq!(right, [1, 2, 3, 4]);

    let mut left = vec![0;4];
    let mut right = vec![0;4];
    a.par_iter().cloned().unzip_into_vecs(&mut left, &mut right);
    assert_eq!(left, [0, 1, 2, 3]);
    assert_eq!(right, [1, 2, 3, 4]);
}
  • partition
  • partition_map
  • intersperse

fn main(){
// partition - Разделяет элементы параллельного итератора на пару произвольных  ParallelExtend контейнеров.
// Элементы, для которых predicate возвращает true, входят в первый контейнер, а остальные идут во второй.
    let (left, right): (Vec<_>, Vec<_>) = (0..8).into_par_iter().partition(|x| x % 2 == 0);
    assert_eq!(left, [0, 2, 4, 6]);
    assert_eq!(right, [1, 3, 5, 7]);
}


fn main(){
  // partition_map - Разделяет и сопоставляет элементы параллельного итератора в пару произвольных ParallelExtend контейнеров.
    // Either::Left предметы входят в первый контейнер, а Either::Rightпредметы переходят во второй.
    use rayon::iter::Either;
    let (left, right): (Vec<_>, Vec<_>) = (0..8).into_par_iter()
        .partition_map(|x| {
            if x % 2 == 0 {
                Either::Left(x * 4)
            } else {
                Either::Right(x * 3)
            }
        });
    assert_eq!(left, [0, 8, 16, 24]);
    assert_eq!(right, [3, 9, 15, 21]);
}


fn main(){
// intersperse -  Перемещает клоны элемента между элементами этого итератора.
    let x = vec![1, 2, 3, 4];
    let r: Vec<_> = x.into_par_iter().intersperse(-100).collect();
    assert_eq!(r, vec![1, -100, 2, -100, 3, -100, 4]);
}

rayon::iter::split


fn split_range1(r: Range) -> (Range, Option>) {
      // Мы математически не можем разделить диапазон, если есть только
      // одна точка внутри него, но мы могли бы прекратить расщепление до этого.
      if r.end - r.start <= 1 { return (r, None); }

     // Здесь наш ассортимент считается достаточно большим, чтобы его можно было разделить
     let midpoint = r.start + (r.end - r.start) / 2;
     (r.start..midpoint, Some(midpoint..r.end))
}
fn main(){
   // split Функция принимает произвольные данные и замыкание , которое знает , как разделить его, и превращает это в ParallelIterator.

  // Используя iter::split, Rayon разделит диапазон, пока не будет достаточно работы
    // чтобы подать ядра процессора, затем дать нам результирующие поддиапазон
    iter::split(0..4096, split_range1).for_each(|sub_range| {
        // Поскольку у нашего начального диапазона был размер степени двойки, заключительные поддиапазоны
        // тоже должен иметь степень двойки
        assert!((sub_range.end - sub_range.start).is_power_of_two());
    });


    // assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
    rayon::iter::split((0..10_usize),|r:Range|{
        if r.end - r.start <= 1 { return (r, None); }
        let midpoint = r.start + (r.end - r.start) / 2;
        (r.start..midpoint, Some(midpoint..r.end))
    }).for_each(|sub_range:Range| {
        //assert!((sub_range.end - sub_range.start).is_power_of_two());
         println!("{}",sub_range.start);// 1 2 3 8 5 4 7 9 0 6
    });
}
Output:
(0..2),(2..5)
(5..7),(7..10)
(0..1),(1..2)
(2..3),(3..5)
(5..6),(6..7)
(7..8),(8..10)
(8..9),(9..10)
(3..4),(4..5)
--------------
(0..5),(5..10) => {  
                   { 
                    (0..2),(2..5) => {
                                      (0..1),(1..2) => {
                                                       None,
                                                       None,
                                                       },
                                      (2..3),(3..5) => {
                                                       None,
                                                       (3..4),(4..5)
                                                       },
                                     },
                    (5..7),(7..10) => {
                                      (5..6),(6..7) => {},
                                      (7..8),(8..10) => {
                                                         None,
                                                         (8..9),(9..10)
                                                         },
                                     }       
                   }, 
                  }


fn main(){
 let (sender, receiver):(Sender,Receiver) = channel();
    let a: Vec =   rayon::iter::split((0..10_i32),|r:Range|{
        if r.end - r.start <= 1 { return (r, None); }
        let midpoint = r.start + (r.end - r.start) / 2;
        //println!("({}..{}),({}..{})",r.start,midpoint,midpoint,r.end);
        (r.start..midpoint, Some(midpoint..r.end))
    })
        .into_par_iter()
        .map_with(sender, |s:&mut Sender, x:Range| {
            s.send(x.end).unwrap();  
            s.send(x.start).unwrap();     // отправка значений i32 через канал
            x.start
        })
        .collect();
    let mut b: Vec = receiver.iter().collect();
}
  • collect_into_vec - Преобразует итератор в вектор
  • unzip_into_vecs - Преобразует итератор в два вектора поровну
  • zip - Создает вектор кортежей из двух итератора и вектора
  • zip_eq - Как zip, но с одинаковой длиной
  • interleave - Слияние векторов полностью
  • interleave_shortest - Слияние с равной длиной
  • chunks - Разделите итератор на куски фиксированного размера.
  • cmp - Сравнение Ordering
  • partial_cmp - Сравнение Ordering
  • eq
  • ne
  • lt
  • le
  • gt
  • ge
  • enumerate - Устанавливает индекс вместе с каждым элементом.
  • skip - Пропуск первые элементы
  • take - Отдает первые элементы
  • position_any - Ищет по предикату возвращая индекс первого совпавшего значения
  • position_first
  • position_last
  • rev - Переворачивает итератор
  • with_min_len - Устанавливает min / max длину итераторов, для обработки в каждом потоке.
  • with_max_len

fn main(){
//len - Производит точное подсчет количества элементов, которые этот итератор будет производить, не допуская паники
    let par_iter = (0..100).into_par_iter().zip(vec![0; 10]);
    assert_eq!(par_iter.len(), 10);
    let vec: Vec<_> = par_iter.collect();
    assert_eq!(vec.len(), 10);
}


fn main(){
// Собирает зультаты итератора в указанный вектор. Вектор всегда усекается до начала выполнения.
    let mut vec = vec![-1, -2, -3];
    (0..5).into_par_iter().collect_into_vec(&mut vec);
    assert_eq!(vec, [0, 1, 2, 3, 4]);
}


fn main(){
// Разархивирует результаты итератора в указанные векторы. Векторы всегда усекаются до начала выполнения.
    let mut left = vec![42; 10];
    let mut right = vec![-1; 10];
    (10..15).into_par_iter().enumerate().unzip_into_vecs(&mut left, &mut right);
    assert_eq!(left, [0, 1, 2, 3, 4]);
    assert_eq!(right, [10, 11, 12, 13, 14]);
}


fn main(){
// zip - Итерации над кортежами (A, B), где элементы A из этого итератора, и B из итератора, заданного в качестве аргумента
    let result: Vec<_> = (1..4)
      .into_par_iter()
      .zip(vec!['a', 'b', 'c'])
      .collect();
    assert_eq!(result, [(1, 'a'), (2, 'b'), (3, 'c')]);
}


fn main(){
// То же самое Zip, но требует, чтобы оба итератора имели одинаковую длину
    let one = [1u8,2];
    let two:[&str;2] = ["t", "e"];
    let one_iter = one.par_iter();
    let two_iter = two.par_iter();
    let zipped: Vec<(&u8, &&str)> = one_iter.zip_eq(two_iter).collect();
    println!("{:?}",zipped);// [(1, "t"), (2, "e")]
}


fn main(){
// interleave - Перемещайте элементы этого итератора и другого заданного итератора.
    let (x, y) = (vec![1, 2], vec![3, 4, 5, 6]);
    let r: Vec = x.into_par_iter().interleave(y).collect();
    assert_eq!(r, vec![1, 3, 2, 4, 5, 6]);
}


fn main(){
// interleave_shortest - Перемещайте элементы этого итератора и другого заданного итератора, пока он не исчерпан
    let (x, y) = (vec![1, 2, 3, 4], vec![5, 6]);
    let r: Vec = x.into_par_iter().interleave_shortest(y).collect();
    assert_eq!(r, vec![1, 5, 2, 6, 3]);
}

chunks


fn main(){
// chunks - Разделите итератор на куски фиксированного размера.
    let a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let r: Vec> = a.into_par_iter().chunks(3).collect();
    assert_eq!(r, vec![vec![1,2,3], vec![4,5,6], vec![7,8,9], vec![10]]);
}
  • cmp
  • partial_cmp
  • enumerate
  • skip
  • take

fn main(){
// cmp - сравнение
    use std::cmp::Ordering::*;
    let x = vec![1, 2, 3];
    assert_eq!(x.par_iter().cmp(&vec![1, 3, 0]), Less);
}


fn main(){
// partial_cmp
    use std::cmp::Ordering::*;
    use std::f64::NAN;
    let x = vec![1.0, 2.0, 3.0];
    assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 3.0, 0.0]), Some(Less));
}


fn main(){
// enumerate - Устанавливает индекс вместе с каждым элементом.
    let chars = vec!['a', 'b', 'c'];
    let result: Vec<_> = chars
        .into_par_iter()
        .enumerate()
        .collect();
    assert_eq!(result, [(0, 'a'), (1, 'b'), (2, 'c')]);
}


fn main(){
// skip - Создает итератор, который пропускает первые nэлементы.
    let result: Vec<_> = (0..100)
        .into_par_iter()
        .skip(95)
        .collect();
    assert_eq!(result, [95, 96, 97, 98, 99]);
}


fn main(){
// take - Создает итератор, который дает первые nэлементы.
    let result: Vec<_> = (0..100)
        .into_par_iter()
        .take(5)
        .collect();
    assert_eq!(result, [0, 1, 2, 3, 4]);
}
  • position_any
  • position_first
  • position_last
  • rev

fn main(){
// position_any - Ищет какой-то элемент в параллельном итераторе, который соответствует данному предикату, и возвращает его индекс.
    let a = [1, 2, 3, 3];
    let i = a.par_iter().position_any(|&x| x == 3).expect("found");
    assert!(i == 2 || i == 3);
    assert_eq!(a.par_iter().position_any(|&x| x == 100), None);
}


fn main(){
// rev - Производит новый итератор с элементами этого итератора в обратном порядке.
    let result: Vec<_> = (0..5)
        .into_par_iter()
        .rev()
        .collect();

    assert_eq!(result, [4, 3, 2, 1, 0]);
}
  • with_min_len
  • with_max_len

fn main(){
// min - Устанавливает минимальную длину итераторов, желаемых для обработки в каждом потоке. Район не будет разделяться меньше, чем эта длина, но, конечно, итератор уже может быть меньшим для начала.
// Производители любят zipи interleave будут использовать больше двух минимумов. Цепные итераторы и итераторы внутри flat_mapмогут использовать свою минимальную длину.
// with_min_len
    let min = (0..1_000_000)
        .into_par_iter()
        .with_min_len(1234)
        .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment
        .min().unwrap();
    assert!(min >= 1234);
}


fn main(){
// with_max_len
    let max = (0..1_000_000)
        .into_par_iter()
        .with_max_len(1234)
        .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment
        .max().unwrap();
    assert!(max <= 1234);
}
  • par_chunks_exact_mut
  • par_chunks_mut
  • par_rchunks_exact_mut
  • par_rchunks_mut
  • par_sort
  • par_sort_by
  • par_sort_by_cached_key
  • par_sort_by_key
  • par_sort_unstable
  • par_sort_unstable_by
  • par_sort_unstable_by_key
  • par_split_mut

perf-book/iterators


use rayon::prelude::*;
fn main(){
    let mut array = [1, 2, 3, 4, 5];
    array.par_chunks_mut(2)
       .for_each(|slice| slice.reverse());
    assert_eq!(array, [2, 1, 4, 3, 5]);
}

Дополнительные адаптеры итератора, функции и макросы.

  • all - Проверьте, выполняется ли предикат для всех элементов в итерируемом объекте.
  • any - Test Проверьте, выполняется ли предикат для любых элементов в итерируемом объекте.
  • assert_equal - Утверждают, что два итератора производят равные последовательности с той же семантикой, что и equal(a, b).
  • chain - Создайте итератор, который сначала выполняет итерацию, i а затем j.
  • cloned - Создайте итератор, который клонирует каждый элемент от &T до T
  • concat - Объедините все элементы итератора в один элемент с помощью Extend.
  • cons_tuples - Создайте итератор, который отображает, например, итераторы ((A, B), C)для (A, B, C).
  • diff_with - Сравнивает каждый элемент, полученный обоими i и jс заданной функцией в lock-step, и возвращает, Diff который описывает, чем j отличается от i.
  • enumerate - Итерировать iterable с текущим индексом.
  • equal - Вернуть, true если обе итерации производят равные последовательности (элементы попарно равны и последовательности одинаковой длины), в false противном случае.
  • fold - Выполните операцию сворачивания над итерируемым объектом.
  • interleave - Создайте итератор, который чередует элементы в i и j.
  • iterate - Создает новый итератор, который бесконечно применяет функцию к значению и дает результаты.
  • join - Объедините все элементы итератора в одну строку, разделенную символом sep
  • kmerge - Создайте итератор, который объединяет элементы содержащихся в нем итераторов, используя функцию упорядочивания.
  • kmerge_by - Создайте итератор, который объединяет элементы содержащихся итераторов.
  • max - Вернуть максимальное значение итерируемого.
  • merge - Создайте итератор, объединяющий элементы в i и j.
  • merge_join_by - Верните адаптер итератора, который объединяет элементы двух базовых итераторов в порядке возрастания.
  • min - Вернуть минимальное значение итерируемого.
  • multipeek - Адаптер итератора, который позволяет пользователю просматривать несколько .next() значений, не продвигая базовый итератор.
  • multizip - Итератор, который обобщает .zip() и позволяет запускать несколько итераторов синхронно.
  • partition - Разделите последовательность с помощью предиката, pred чтобы элементы, которым сопоставляются true, помещались перед элементами, которым сопоставляются false.
  • peek_nth - Подстановочная замена, для std::iter::Peekable которой добавлен peek_nth метод, позволяющий пользователю peek продвигать значение на несколько итераций вперед, не продвигая базовый итератор.
  • process_results - «Поднимите» функцию значений итератора, чтобы Result вместо этого он мог обрабатывать итератор значений.
  • put_back - Создайте итератор, в который вы можете вернуть один элемент
  • put_back_n - Создайте итератор, в котором вы можете вернуть несколько значений в начало итерации.
  • rciter - Вернуть итератор внутри Rc<RefCell<_>> оболочки.
  • repeat_n Создайте итератор, который производит n повторение element.
  • rev - Выполните итерацию iterable в обратном порядке.
  • sorted - Отсортируйте все элементы итератора в новый итератор в порядке возрастания.
  • unfold - Создает новый источник разворачивания с указанным замыканием в качестве «функции итератора» и начальным состоянием для перехода к замыканию.
  • zip - Итерировать i и синхронно j
  • zip_eq - Итерировать i и синхронно j

use itertools::Itertools;
fn main(){
    assert!(itertools::all(&[1, 2, 3], |elt| *elt > 0));
}