柚子快報激活碼778899分享:rust學習-迭代器
柚子快報激活碼778899分享:rust學習-迭代器
迭代器的實現(xiàn)方式提供了對多種不同的序列使用相同邏輯的靈活性 沒有迭代器時只能用索引,迭代器處理了所有這些邏輯,減少了重復(fù)代碼,消除了潛在的混亂
示例
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
// 無需使 v1_iter 可變,因為 for 循環(huán)會獲取 v1_iter 的所有權(quán)并在后臺使 v1_iter 可變
for val in v1_iter {
println!("Got: {}", val);
}
}
原理
迭代器都實現(xiàn)了一個叫做 Iterator 的定義于標準庫的 trait
pub trait Iterator {
// type Item 和 Self::Item 定義了 trait 的 關(guān)聯(lián)類型,associated type
// 實現(xiàn) Iterator trait 要求同時定義一個 Item 類型
// 這個 Item 類型被用作 next 方法的返回值類型
type Item;
// next 一次返回迭代器中的一個項,封裝在 Some 中
// 當?shù)鹘Y(jié)束時,它返回 None
fn next(&mut self) -> Option
// 此處省略了方法的默認實現(xiàn)
}
使用iter執(zhí)行一個個的遍歷
#[test]
fn iterator_demonstration() {
let v1 = vec![1, 2, 3];
// v1_iter 可變
// 在迭代器上調(diào)用 next 方法改變了迭代器中用來記錄序列位置的狀態(tài)
// 從 next 調(diào)用中得到的值是 vector 的不可變引用
let mut v1_iter = v1.iter();
assert_eq!(v1_iter.next(), Some(&1));
assert_eq!(v1_iter.next(), Some(&2));
assert_eq!(v1_iter.next(), Some(&3));
assert_eq!(v1_iter.next(), None);
}
iter:生成一個不可變引用的迭代器 into_iter:獲取 v1 所有權(quán)并返回擁有所有權(quán)的迭代器 iter_mut:迭代可變引用
消費適配器
調(diào)用它們會消耗迭代器 比如sum:獲取迭代器的所有權(quán)并反復(fù)調(diào)用 next 來遍歷迭代器,因而會消費迭代器。當其遍歷每一個項時,它將每一個項加總到一個總和并在迭代完成時返回總和
#[test]
fn iterator_sum() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
// 調(diào)用 sum 之后不再允許使用 v1_iter 因為調(diào)用 sum 時它會獲取迭代器的所有權(quán)
let total: i32 = v1_iter.sum();
assert_eq!(total, 6);
}
迭代器適配器
將當前迭代器變?yōu)椴煌愋偷牡鳌?可以鏈式調(diào)用多個迭代器適配器。 因為所有迭代器都惰性,必須調(diào)用一個消費適配器方法以便獲取迭代器適配器調(diào)用的結(jié)果
使用閉包自定義行為同時,復(fù)用 Iterator trait 提供的迭代行為
let v1: Vec
// 調(diào)用 map 方法創(chuàng)建一個新迭代器,調(diào)用 collect 方法消費新迭代器并創(chuàng)建一個 vector
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);
// 編譯如下代碼將會warn,因為惰性迭代器沒人使用,需要像上述那樣,用collect觸發(fā)下使用
// v1.iter().map(|x| x + 1);
使用閉包獲取環(huán)境
使用 filter 迭代器適配器和捕獲環(huán)境的閉包
迭代器的 filter 方法獲取一個使用迭代器的每一個項并返回布爾值的閉包。如果閉包返回 true,其值將會包含在 filter 提供的新迭代器中。 如果閉包返回 false,其值不會包含在結(jié)果迭代器中
#[derive(PartialEq, Debug)]
struct Shoe {
size: u32,
style: String,
}
fn shoes_in_my_size(shoes: Vec
// into_iter:獲取一個vector 的所有權(quán)
shoes.into_iter()
// shoe_size 是環(huán)境,函數(shù)做不到,但是閉包可以做到
// filter 將這個迭代器適配成一個只含有那些閉包返回 true 的元素的新迭代器
.filter(|s| s.size == shoe_size)
// 消費迭代器
.collect()
}
#[test]
fn filters_by_size() {
let shoes = vec![
Shoe { size: 10, style: String::from("sneaker") },
Shoe { size: 13, style: String::from("sandal") },
Shoe { size: 10, style: String::from("boot") },
];
let in_my_size = shoes_in_my_size(shoes, 10);
assert_eq!(
in_my_size,
vec![
Shoe { size: 10, style: String::from("sneaker") },
Shoe { size: 10, style: String::from("boot") },
]
);
}
創(chuàng)建自定義迭代器
實現(xiàn) Iterator trait 只會從 1 數(shù)到 5 的迭代器
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option
self.count += 1;
if self.count < 6 {
Some(self.count)
} else {
None
}
}
}
#[test]
fn calling_next_directly() {
let mut counter = Counter::new();
assert_eq!(counter.next(), Some(1));
assert_eq!(counter.next(), Some(2));
assert_eq!(counter.next(), Some(3));
assert_eq!(counter.next(), Some(4));
assert_eq!(counter.next(), Some(5));
assert_eq!(counter.next(), None);
}
其他 Iterator trait 方法使用自定義迭代器的next
#[test]
fn using_other_iterator_trait_methods() {
let sum: u32 = Counter::new()
// 獲取 Counter 實例產(chǎn)生的值
// 將這些值與另一個 Counter 實例在省略了第一個值之后產(chǎn)生的值配對
.zip(Counter::new().skip(1))
// 將每一對值相乘
.map(|(a, b)| a * b)
// 只保留那些可以被3整除的結(jié)果
.filter(|x| x % 3 == 0)
// 將所有保留的結(jié)果相加
.sum();
assert_eq!(18, sum);
}
zip 只產(chǎn)生四對值; 第五對值 (5, None) 從未被產(chǎn)生 zip 在任一輸入迭代器返回 None 時也返回 None
柚子快報激活碼778899分享:rust學習-迭代器
推薦閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。