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