картина

картина


0x00 Просмотр и открытие

На этом изучение функций подошло к концу, в этом уроке мы познакомимся с итераторами. При объяснении цикла for ранее мы использовали индекс для обхода каждого элемента.Если позиция индекса не требуется в процессе обхода, рекомендуется использовать итератор для обхода коллекции данных.

0x01 определение итератора

Шаблон итератора абстрагирует поведение обхода коллекции данных в отдельный итеративный объект и передает все элементы коллекции в логику обработки по порядку при обходе коллекции. Итератор — это трейт .

черта  Итератор  {

    тип Товар;

    fn next(&mut self) -> Option<Self::Item>

    // другие методы

}

Выше приведен упрощенный трейт итератора . Item это тип значения, создаваемого во время итерации итератора. Возвращаемое значение следующего метода — Option . Если он возвращает Some(v) , v представляет следующее значение итератора. Если он возвращает None , итератор завершится. Мы можем получить итератор с помощью метода iter() коллекции , а переменная, получающая итератор, должна быть изменяемой. Другие методы внутри итератора пока игнорируются. Черты будут представлены в последующих главах.

Пример кода выглядит следующим образом:

    let vec = vec![3,4,5];

    let mut iter = vec.iter();


dbg!(iter.next());

    dbg!(iter.next());

    dbg!(iter.next());

    dbg!(iter.next());

Результат запуска кода:

[src\main.rs:6] iter.next() = Some(3,)

[src\main.rs:7] iter.next() = Some(4,)
[src\main.rs:8] iter.next() = Some(5,)
[src\main.rs:9] iter.next() = None

0x02 Итераторы и циклы for

Итераторы также можно использовать с циклами for. Использовать итераторы в сочетании с for относительно просто, и вы можете сразу перейти к коду.

Пример кода выглядит следующим образом:

    let vec_for = vec![1, 2, 3, 4, 5];

for i in vec_for.iter() {
print!("{} ", i);
}

Результат запуска кода:

1 2 3 4 5

0x03 Итераторы и потребители

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

sum - потребитель суммирования

Он может перейти к элементам в итераторе для накопления. Пример кода выглядит следующим образом:

    пусть vec_consumer = vec! [ 2 , 4 , 6 , 8 , 10 ] ;

let sum_result: i32 = vec_consumer.iter().sum();
dbg!(sum_result);

Результат запуска кода:

sum_result = 30

любой - условный потребитель

Он может определить, есть ли в итераторе элемент, удовлетворяющий определенному условию. Возвращаемое значение имеет логический тип. Пример кода выглядит следующим образом:

    let vec_consumer = vec![2, 4, 6, 8, 10];

let any_result = vec_consumer.iter().any(|x| *x % 2 != 0);
dbg!(any_result);

Результат запуска кода:

any_result = false

собирать - собирать потребителя

Он может преобразовать итератор в указанный тип контейнера. Следующий пример кода выглядит следующим образом:

let collect_result: Vec<i32> = vec_consumer.iter().map(|x| x - 1).collect();


dbg!(collect_result);

Результат запуска кода:

collect_result = [

1,
3,
5,
7,

9,

]

Приведенный выше код использует метод карты, чтобы каждый элемент вызывал метод в замыкании, и, наконец, собирает элементы для создания нового контейнера. Метод карты описан ниже.

0x04 Итераторы и адаптеры

В трейте Iterator также есть ряд методов , называемых адаптерами, которые также поддерживают цепочку. Распространенными методами адаптера являются map, take, filter, rev, zip и т. д. Ниже приводится подробное введение.

карта

Метод карты позволяет каждому элементу вызывать метод в замыкании и, наконец, собирает элементы для создания нового контейнера. Часто используется в сочетании с методом collect . Он уже был представлен выше и не будет повторяться здесь.

брать

Создает новый итератор, который выполняет итерацию только первых n элементов исходного итератора. Часто используется в сценариях, где переменная указывает несколько элементов. Генерируется структура Take , содержащая исходный итератор и длину. Знания о структурах будут введены в следующем разделе. Пример кода выглядит следующим образом:

    let vec_adapter = vec![1, 3, 5, 7, 9];

let take_result = vec_adapter.iter().take(3);
dbg!(take_result);

Результат запуска кода:

take_result = Take {

iter: Iter(
[
1,
3,
5,
7,
9,
],
),

n: 3,

}

фильтр

Вызов замыкания для каждого элемента в итераторе создает новый итератор, который фильтрует элементы. Возвращаемое значение замыкания должно быть логического типа. Если true , текущий элемент помещается в итератор, иначе текущий элемент будет проигнорирован. Наконец, его нужно собрать в новый итератор с помощью метода collect . Пример кода выглядит следующим образом:

    let filter_result: Vec<i32> = vec_adapter.iter().map(|x| *x + 2).filter(|x| *x % 3 == 0).collect();


dbg!(filter_result);

Результат запуска кода:

filter_result = [

3,

9,

]

оборот

Переверните итератор, чтобы сгенерировать новый итератор. Возвращаемое значение представляет собой структуру Rev , которая перемещается сзади вперед при обходе структуры. Пример кода выглядит следующим образом:

    let rev_result = vec_adapter.iter().rev();

dbg!(&rev_result);
for i in rev_result {
print!("{} ", i);
}

Результат запуска кода:

&rev_result = Rev {

iter: Iter(
[
1,
3,
5,
7,
9,
],

),

}

9 7 5 3 1

молния

Сожмите два итератора в новый итератор. На самом деле он будет перебирать оба итератора одновременно и возвращать кортеж с первым элементом из первого итератора и вторым элементом из второго итератора. Пример кода выглядит следующим образом:

    let vec1 = vec![3, 5, 7];

let vec2 = vec![2, 4, 6];
let vec_zip: Vec<i32> = vec1.iter().zip(vec2.iter()).map(|x| { x.0 + x.1 }).collect();
dbg!(vec_zip);

Результат запуска кода:

vec_zip = [

5,
9,

13,

]

PS: если один из двух итераторов возвращает None в процессе итерации, zip адаптера вернет None.

0x04 Сводка

В этом разделе описываются некоторые основные способы использования итераторов.Обычно используемые методы итераторов — это any, map, filter и collect . На самом деле об итераторах можно рассказать намного больше, и этот урок — лишь краткое введение в них. Я продолжу объяснять более сложное использование итераторов в расширенной главе.

0x05 Исходный код этого раздела

Нажмите ниже, чтобы прочитать исходный текст, чтобы получить исходный код этого курса бесплатно

Предварительный просмотр следующего раздела — Структура (выше).

картина