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 Исходный код этого раздела
Нажмите ниже, чтобы прочитать исходный текст, чтобы получить исходный код этого курса бесплатно
Предварительный просмотр следующего раздела — Структура (выше).