柚子快報激活碼778899分享:開發(fā)語言 后端 rust迭代器
柚子快報激活碼778899分享:開發(fā)語言 后端 rust迭代器
迭代器用來遍歷容器。 迭代器就是把容器中的所有元素按照順序一個接一個的傳遞給處理邏輯。
Rust中的迭代器 標準庫中定義了Iterator特性
trait Iterator {
type Item;
fn next(&mut self) -> Option
}
實現(xiàn)了Iterator特性的結(jié)構(gòu)體就是迭代器。 很多類型都有iter()方法,返回一個Iter結(jié)構(gòu)體,該結(jié)構(gòu)體實現(xiàn)了Iterator特性。
一、創(chuàng)建迭代器
Rust中有三種類型的迭代器。 從容器創(chuàng)建迭代器有三種方法。 iter() 返回一個只讀可重入迭代器,迭代器元素的類型為 &T iter_mut() 返回一個可寫可重入迭代器,迭代器元素的類型為 &mut T into_iter() 返回一個只讀不可重入迭代器,迭代器元素的類型為 T
(一)iter() 返回一個只讀可重入迭代器,迭代器元素的類型為&T。
例子
fn main() {
let names = vec!["簡單教程", "簡明教程", "簡單編程"];
let name = names.iter();
println!("{:?}", names);
}
(二)iter_mut() 返回一個可寫可重入迭代器,迭代器元素的類型為&mut T。
例子
fn main() {
let mut names = vec!["簡單教程", "簡明教程", "簡單編程"];
let name = names.iter_mut();
println!("{:?}", names);
}
(三)into_iter() 返回一個只讀不可重入迭代器,迭代器元素的類型為T 它會把容器的值移動到迭代器中。 iter_into()之后的容器不可重用。
例子
fn main() {
let mut names = vec!["簡單教程", "簡明教程", "簡單編程"];
let name = names.into_iter();
println!("{:?}", name);
//println!("{:?}", names);//去掉注釋會編譯錯誤
}
二、使用迭代器
(一)返回迭代器元素個數(shù) count() 消耗迭代器,計算迭代次數(shù)并返回它。 此方法將反復(fù)調(diào)用next(),直到遇到None,并返回它看到Some的次數(shù)。 請注意,即使迭代器沒有任何元素,也必須至少調(diào)用一次next() 溢出行為 該方法無法防止溢出,因此對具有超過usize::MAX個元素的迭代器的元素進行計數(shù)會產(chǎn)生錯誤的結(jié)果或panics。 如果啟用了調(diào)試斷言,則將保證panic。 Panics 如果迭代器具有多個usize::MAX元素,則此函數(shù)可能為panic。 例子
let a = [1, 2, 3];
assert_eq!(a.iter().count(), 3);
(二)訪問迭代器元素 nth(n) 返回迭代器的第n個元素。 計數(shù)從零開始,因此nth(0) 返回第一個值,nth(1) 返回第二個值,依此類推。 請注意,所有先前的元素以及返回的元素都將從迭代器中消耗。這意味著前面的元素將被丟棄,并且在同一迭代器上多次調(diào)用nth(0)將返回不同的元素。 如果n大于或等于迭代器的長度,則nth()將返回None。 例子
let a = [1, 2, 3];
assert_eq!(a.iter().nth(1), Some(&2));
多次調(diào)用nth() 不會回退迭代器:
let a = [1, 2, 3];
let mut iter = a.iter();
assert_eq!(iter.nth(1), Some(&2));
assert_eq!(iter.nth(1), None);
如果n大于或等于迭代器的長度,則返回None:
let a = [1, 2, 3];
assert_eq!(a.iter().nth(10), None);
last() 消耗迭代器,返回最后一個元素。 此方法將評估迭代器,直到返回None。 這樣做時,它會跟蹤當前元素。 返回None之后,last() 將返回它看到的最后一個元素。 例子
let a = [1, 2, 3];
assert_eq!(a.iter().last(), Some(&3));
(三)遍歷迭代器 1.使用next()方法遍歷容器 例子
fn main() {
let a = [10,20,30];
let mut iter = a.iter(); // 從一個數(shù)組中返回迭代器
println!("{:?}",iter);
//使用next() 方法返回迭代器中的下一個元素
println!("{:?}",iter.next());
println!("{:?}",iter.next());
println!("{:?}",iter.next());
println!("{:?}",iter.next());
}
編譯運行結(jié)果如下
Iter([10, 20, 30])
Some(10)
Some(20)
Some(30)
None
2.使用for循環(huán)遍歷 手動調(diào)用next()太麻煩了,推薦使用for循環(huán)來使用迭代器。
(1)iter() 例子
fn main() {
let names = vec!["簡單教程", "簡明教程", "簡單編程"];
for name in names.iter() {
println!("{}", name);
}
println!("{:?}", names);
}
for name in &names 實際上等價于 for name in names.iter()
(2)iter_mut() 例子
fn main() {
let mut names = vec!["簡單教程", "簡明教程", "簡單編程"];
for name in names.iter_mut() {
println!("{}", name);
}
println!("{:?}", names);
}
for name in &mut names 實際上等價于 for name in names.iter_mut()
(3)into_iter() 例子
fn main() {
let names = vec!["簡單教程", "簡明教程", "簡單編程"];
for name in names.into_iter() {
println!("{}", name);
}
//println!("{:?}", names); //去掉注釋會編譯錯誤
}
for name in names 實際上等價于 for name in names.into_iter()
(四)迭代器轉(zhuǎn)換成容器 collect() 將迭代器轉(zhuǎn)換為容器。 使用collect()的最基本模式是將一個容器轉(zhuǎn)換為另一個容器。 在一個容器上調(diào)用iter,進行了一堆轉(zhuǎn)換,最后調(diào)用collect()。 由于collect()非常通用,因此可能導致類型推斷問題。 因此,要指定類型或使用turbofish語法。 例子
let a = [1, 2, 3];
let doubled: Vec
assert_eq!(vec![2, 4, 6], doubled);
使用自動推斷類型
let a = [1, 2, 3];
let doubled: Vec<_> = a.iter().map(|&x| x * 2).collect();
assert_eq!(vec![2, 4, 6], doubled);
使用turbofish
let a = [1, 2, 3];
let doubled = a.iter().map(|x| x * 2).collect::
assert_eq!(vec![2, 4, 6], doubled);
_ 與turbfish一起使用:
let a = [1, 2, 3];
let doubled = a.iter().map(|x| x * 2).collect::
assert_eq!(vec![2, 4, 6], doubled);
(五)迭代器轉(zhuǎn)換 map()方法可以轉(zhuǎn)換迭代器 創(chuàng)建一個迭代器,該迭代器每個元素是由原迭代器元素應(yīng)用閉包得到。 可以這樣考慮map(): 如果您有一個元素類型為A的迭代器,您想要元素類型為B的迭代器,則可以使用map(),傳遞一個把A轉(zhuǎn)成B的閉包。 例子
let a = [1, 2, 3];
let mut iter = a.iter().map(|x| 2 * x);
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(6));
assert_eq!(iter.next(), None);
如果您正在做某種副作用,請首選for而不是map(): 不要這樣做:
(0..5).map(|x| println!("{x}"));// 它甚至不會執(zhí)行,因為它很懶。Rust會就此警告您。
而是用:
for x in 0..5 {
println!("{x}");
}
flat_map() 創(chuàng)建一個迭代器,其工作方式類似于map,但它會將嵌套的結(jié)構(gòu)展平。 map非常有用,但僅當閉包產(chǎn)生值時才使用。 如果它產(chǎn)生一個迭代器,則存在一個額外的間接層。flat_map() 將自行刪除這個間接層。 您可以把flat_map(f) 視為map(f).flatten()。 map的閉包為每個元素返回一個值,而flat_map ()的閉包為每個元素返回一個迭代器。 例子
let words = ["alpha", "beta", "gamma"];
// chars() 返回一個迭代器
let merged: String = words.iter().flat_map(|s| s.chars()).collect();
assert_eq!(merged, "alphabetagamma");
flatten() 創(chuàng)建一個去掉嵌套層的迭代器。比如二維向量變一維向量 例子
let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
let flattened = data.into_iter().flatten().collec::
assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
let words = ["alpha", "beta", "gamma"];
// chars() 返回一個迭代器
let merged: String = words.iter().map(|s| s.chars()).flatten().collect();
assert_eq!(merged, "alphabetagamma");
您也可以用flat_map()來重寫它
let words = ["alpha", "beta", "gamma"];
// chars() 返回一個迭代器
let merged: String = words.iter().flat_map(|s| s.chars()).collect();
assert_eq!(merged, "alphabetagamma");
展平一次只能刪除一層嵌套:
let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
let d2 = d3.iter().flatten().collect::
assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);
let d1 = d3.iter().flatten().flatten().collect::
assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);
在這里,我們看到flatten()僅刪除了一層嵌套。三維數(shù)組變二維而不是一維。要獲得一維,您必須再次flatten()。
(六)enumerate 創(chuàng)建一個迭代器,該迭代器元素是(i, val),其中i是當前迭代索引,val是迭代器返回的值。 enumerate()保持其計數(shù)為usize。 溢出行為 該方法無法防止溢出,因此枚舉多個usize::MAX元素會產(chǎn)生錯誤的結(jié)果或panics。 如果啟用了調(diào)試斷言,則將保證panic。 Panics 如果要返回的索引將溢出usize,則返回的迭代器可能為panic。 例子
let a = ['a', 'b', 'c'];
let mut iter = a.iter().enumerate();
assert_eq!(iter.next(), Some((0, &'a')));
assert_eq!(iter.next(), Some((1, &'b')));
assert_eq!(iter.next(), Some((2, &'c')));
assert_eq!(iter.next(), None);
(七)逆轉(zhuǎn)迭代器 rev 反轉(zhuǎn)迭代器的方向。 通常,迭代器從左到右進行迭代。 使用rev() 之后,迭代器將改為從右向左進行迭代。 例子
let a = [1, 2, 3];
let mut iter = a.iter().rev();
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), None);
(八)截取迭代器 take(n) 創(chuàng)建一個迭代器,它的元素是原迭代器的前n個元素。如果原迭代器元素數(shù)小于n,則返回原迭代器所有元素。 例子
let a = [1, 2, 3];
let mut iter = a.iter().take(2);
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), None);
let v = [1, 2];
let mut iter = v.into_iter().take(5);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), None);
(九)其他 max 返回迭代器的最大元素。 如果幾個元素最大相等,則返回最后一個元素。如果迭代器為空,則返回None。 請注意,由于NaN不可比較,f32/f64沒有實現(xiàn)Ord。 您可以使用Iterator::reduce解決此問題:
assert_eq!([2.4, f32::NAN, 1.3].into_iter().reduce(f32::max).unwrap(),2.4);
例子
let a = [1, 2, 3];
let b: Vec = Vec::new();
assert_eq!(a.iter().max(), Some(&3));
assert_eq!(b.iter().max(), None);
min 返回迭代器的最小元素。 如果幾個元素相等地最小,則返回第一個元素。 如果迭代器為空,則返回None。 請注意,由于NaN不可比較,f32/f64沒有實現(xiàn)Ord。您可以使用Iterator::reduce解決此問題:
assert_eq!([2.4, f32::NAN, 1.3].into_iter().reduce(f32::min).unwrap(),1.3);
例子
let a = [1, 2, 3];
let b: Vec = Vec::new();
assert_eq!(a.iter().min(), Some(&1));
assert_eq!(b.iter().min(), None);
sum 對迭代器的元素求和。 獲取每個元素,將它們添加在一起,然后返回結(jié)果。 空的迭代器將返回該類型的零值。 sum()可用于對任何實現(xiàn)Sum的類型求和,包括Option和Result。 Panics 當調(diào)用sum() 并返回原始整數(shù)類型時,如果計算溢出并且啟用了調(diào)試斷言,則此方法將為panic。 例子
let a = [1, 2, 3];
let sum: i32 = a.iter().sum();
assert_eq!(sum, 6);
柚子快報激活碼778899分享:開發(fā)語言 后端 rust迭代器
文章來源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。