RUST learning diary lesson 21 - iterator

Keywords: Rust

RUST learning diary lesson 21 - iterator

0x00 review and opening

The study of functions is over for the time being. This lesson is about iterators. When explaining the for loop earlier, we used the index to traverse each element. If the index position is not required in the traversal process, it is recommended to use the iterator to traverse the data set.

0x01 definition of iterator

The iterator pattern abstracts the behavior of traversing the data set into a separate iterative object, and passes all the elements in the set to the processing logic in order when traversing the set. Iterator is a trait.

trait Iterator {

​ type Item;

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

//Other methods

}

The above is a simplified Iterator trait, and Item is the type of value generated during Iterator iteration. The return value of the next method is an Option. If Some(v) is returned, v represents the next value of the Iterator. If None is returned, the Iterator will terminate. We can get the Iterator through the iter() method of the collection, and the variable receiving the Iterator must be variable. Other methods within the Iterator are temporarily ignored. Trait will be introduced in the following chapters.

The example code is as follows:

let vec = vec![3,4,5];
let mut iter = vec.iter();

dbg!(iter.next());
dbg!(iter.next());
dbg!(iter.next());
dbg!(iter.next());

Code run result:

[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 iterator and for loop

Iterators can also be used with a for loop. Iterator and for are relatively simple to use, and can be directly used in the code.

The example code is as follows:

	let vec_for = vec![1, 2, 3, 4, 5];
    for i in vec_for.iter() {
        print!("{} ", i);
    }

Code run result:

1 2 3 4 5 

0x03 iterator and consumer

If only iterators are used, it is basically meaningless. Because it does not iterate by itself, it can be used in conjunction with the for loop. Of course, some other methods, called consumers, are defined in the Iterator trait.

sum -- summation consumer

It can accumulate the elements in the iterator. The example code is as follows:

	let vec_consumer = vec![2, 4, 6, 8, 10];
    let sum_result: i32 = vec_consumer.iter().sum();
    dbg!(sum_result);

Code run result:

sum_result = 30
any -- conditional consumer

It can determine whether there are elements in the iterator that meet a certain condition. The return value is Boolean. The example code is as follows:

	let vec_consumer = vec![2, 4, 6, 8, 10];
	let any_result = vec_consumer.iter().any(|x| *x % 2 != 0);
    dbg!(any_result);

Code run result:

any_result = false
Collect -- collect consumer

It converts the iterator to the specified container type. The following example code is as follows:

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

Code run result:

collect_result = [
    1,
    3,
    5,
    7,
    9,
]

The above code uses the map method to make each element call the method in the closure, and finally collects the elements to generate a new container. The map method is described below.

0x04 iterators and adapters

There are also a series of methods called adapters in Iterator trait, which also support chained calls. Common adapter methods include map, take, filter, rev, zip, etc. The following is a detailed introduction.

map

map method can make each element call the method in the closure, and finally collect the elements to generate a new container. Often used in conjunction with the collect method. It has been introduced above, so I won't repeat it here.

take

Generate a new iterator that iterates only the first n elements of the original iterator. Commonly used in scenarios where variables specify the number of elements. The generated is a Take structure, including the original iterator and length. The knowledge about structures will be introduced in the next section. The example code is as follows:

	let vec_adapter = vec![1, 3, 5, 7, 9];
    let take_result = vec_adapter.iter().take(3);
    dbg!(take_result);

Code run result:

take_result = Take {
    iter: Iter(
        [
            1,
            3,
            5,
            7,
            9,
        ],
    ),
    n: 3,
}
filter

A closure is called on each element in the iterator to generate a new iterator that filters the elements. The return value of closure must be Boolean. If true, the current element is placed in the iterator. Otherwise, the current element will be ignored. Finally, it needs to be collected into a new iterator through the collect method. The example code is as follows:

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

Code run result:

filter_result = [
    3,
    9,
]
rev

After reversing the iterator, a new iterator is generated. The return value is the Rev structure. When traversing the structure, it will be traversed from back to front. The example code is as follows:

	let rev_result = vec_adapter.iter().rev();
    dbg!(&rev_result);
    for i in rev_result {
        print!("{} ", i);
    }

Code run result:

&rev_result = Rev {
    iter: Iter(
        [
            1,
            3,
            5,
            7,
            9,
        ],
    ),
}
9 7 5 3 1 
zip

Compress the two iterators into a new iterator. In fact, two iterators will iterate at the same time and return a tuple. The first element is from the first iterator and the second element is from the second iterator. The example code is as follows:

	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);

Code run result:

vec_zip = [
    5,
    9,
    13,
]

PS: if one of the two iterators returns the type None during the iteration, the adapter zip will return None.

0x04 summary

This section describes the basic usage of iterators. The commonly used iterator methods are generally any, map, filter and collect. There's a lot more about iterators. This lesson just briefly introduces iterators. I will continue to explain the more advanced use of iterators in the advanced chapter.

0x04 source code of this section

021. StudyRust - Code cloud - Open Source China (gitee.com)

The next section is the notice - structure.

Posted by jigen7 on Sat, 20 Nov 2021 04:04:25 -0800