0x00 Revisión y Apertura
El estudio de las funciones ha llegado a su fin por el momento, en esta lección aprenderemos acerca de los iteradores. Cuando explicamos el bucle for anteriormente, usamos el índice para recorrer cada elemento. Si la posición del índice no es necesaria durante el proceso de recorrido, se recomienda usar el iterador para recorrer la recopilación de datos.
definición del iterador 0x01
El patrón iterador abstrae el comportamiento de recorrer la colección de datos en un objeto iterativo separado y pasa todos los elementos de la colección a la lógica de procesamiento en orden al recorrer la colección. El iterador es un rasgo .
iterador de rasgos {
tipo Artículo;
fn next(&mut self) -> Option<Self::Item>
// otros metodos
}
Lo anterior es un rasgo de iterador simplificado , Item es el tipo de valor producido durante la iteración del iterador. El valor de retorno del siguiente método es una opción . Si devuelve Some(v) , v representa el siguiente valor del iterador. Si devuelve None , el iterador terminará. Podemos obtener el iterador a través del método iter() de la colección , y la variable que recibe el iterador debe ser mutable. Otros métodos dentro del iterador se ignoran por ahora. Los rasgos se introducirán en capítulos posteriores.
El código de ejemplo es el siguiente:
let vec = vec![3,4,5];
let mut iter = vec.iter();
dbg!(iter.next());
dbg!(iter.next());
dbg!(iter.next());
dbg!(iter.next());
El resultado de ejecutar el código:
[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 Iteradores y bucles for
Los iteradores también se pueden usar con bucles for. Es relativamente simple usar iteradores junto con for, y puede ir directamente al código.
El código de ejemplo es el siguiente:
let vec_for = vec![1, 2, 3, 4, 5];
for i in vec_for.iter() {
print!("{} ", i);
}
El resultado de ejecutar el código:
1 2 3 4 5
0x03 Iteradores y consumidores
Básicamente no tiene sentido si solo usa iteradores. Debido a que no itera por sí mismo, puede usarse con bucles for como se describió anteriormente. Por supuesto, algunos otros métodos también se definen en el rasgo Iterator , llamados consumidores.
sum - consumidor de suma
Puede ir a los elementos en el iterador para acumular. El código de ejemplo es el siguiente:
sea vec_consumer = vec! [ 2 , 4 , 6 , 8 , 10 ] ;
let sum_result: i32 = vec_consumer.iter().sum();
dbg!(sum_result);
El resultado de ejecutar el código:
sum_result = 30
cualquiera - consumidor condicional
Puede determinar si hay un elemento en el iterador que satisfaga una determinada condición. El valor de retorno es de tipo booleano. El código de ejemplo es el siguiente:
let vec_consumer = vec![2, 4, 6, 8, 10];
let any_result = vec_consumer.iter().any(|x| *x % 2 != 0);
dbg!(any_result);
El resultado de ejecutar el código:
any_result = false
recoger - recoger consumidor
Puede convertir el iterador al tipo de contenedor especificado. El siguiente código de ejemplo es el siguiente:
let collect_result: Vec<i32> = vec_consumer.iter().map(|x| x - 1).collect();
dbg!(collect_result);
El resultado de ejecutar el código:
collect_result = [
1,
3,
5,
7,
9,
]
El código anterior usa el método map para permitir que cada elemento llame al método en el cierre y finalmente recopila los elementos para generar un nuevo contenedor. El método del mapa se describe a continuación.
0x04 Iteradores y adaptadores
También hay una serie de métodos en el atributo Iterator llamados adaptadores que también admiten el encadenamiento. Los métodos comunes de adaptador son map, take, filter, rev, zip , etc. La siguiente es una introducción detallada.
mapa
El método del mapa permite que cada elemento llame al método en el cierre y, finalmente, recopila los elementos para generar un nuevo contenedor. A menudo se utiliza junto con el método de recopilación . Ya se ha presentado anteriormente y no se repetirá aquí.
tomar
Genera un nuevo iterador que itera solo los primeros n elementos del iterador original. A menudo se usa en escenarios donde una variable especifica una cantidad de elementos. Lo que se genera es una estructura Take que contiene el iterador y la longitud originales. El conocimiento sobre las estructuras se introducirá en la siguiente sección. El código de ejemplo es el siguiente:
let vec_adapter = vec![1, 3, 5, 7, 9];
let take_result = vec_adapter.iter().take(3);
dbg!(take_result);
El resultado de ejecutar el código:
take_result = Take {
iter: Iter(
[
1,
3,
5,
7,
9,
],
),
n: 3,
}
filtrar
Llamar al cierre en cada elemento del iterador produce un nuevo iterador que filtra los elementos. El valor de retorno del cierre debe ser de tipo booleano. Si es verdadero , el elemento actual se coloca en el iterador; de lo contrario, se ignorará el elemento actual. Finalmente, debe recopilarse en un nuevo iterador a través del método de recopilación . El código de ejemplo es el siguiente:
let filter_result: Vec<i32> = vec_adapter.iter().map(|x| *x + 2).filter(|x| *x % 3 == 0).collect();
dbg!(filter_result);
El resultado de ejecutar el código:
filter_result = [
3,
9,
]
Rvdo
Invierta el iterador para generar un nuevo iterador. El valor de retorno es la estructura Rev , que se recorre de atrás hacia adelante al atravesar la estructura. El código de ejemplo es el siguiente:
let rev_result = vec_adapter.iter().rev();
dbg!(&rev_result);
for i in rev_result {
print!("{} ", i);
}
El resultado de ejecutar el código:
&rev_result = Rev {
iter: Iter(
[
1,
3,
5,
7,
9,
],
),
}
9 7 5 3 1
Código Postal
Comprima dos iteradores en un nuevo iterador. En realidad iterará sobre ambos iteradores al mismo tiempo y devolverá una tupla con el primer elemento del primer iterador y el segundo elemento del segundo iterador. El código de ejemplo es el siguiente:
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);
El resultado de ejecutar el código:
vec_zip = [
5,
9,
13,
]
PD: si uno de los dos iteradores devuelve Ninguno durante el proceso de iteración, el zip del adaptador devolverá Ninguno.
0x04 Resumen
En esta sección se describen algunos usos básicos de los iteradores. Los métodos de iterador más utilizados son generalmente any, map, filter y collect . En realidad, hay mucho más sobre los iteradores. Esta lección es solo una breve introducción a los iteradores. Continuaré explicando el uso más avanzado de los iteradores en el capítulo avanzado.
0x05 El código fuente de esta sección
Haga clic a continuación para leer el texto original y obtener el código fuente de este curso de forma gratuita
Vista previa de la siguiente sección - Estructura (arriba).