Rust 學習筆記:迭代器

Rust 學習筆記:迭代器

  • Rust 學習筆記:迭代器
    • Iterator trait 和 next 方法
    • 使用迭代器的方法
    • 生成其他迭代器的方法
    • 使用閉包捕獲它們的環境

Rust 學習筆記:迭代器

在 Rust 中,迭代器負責遍歷每個項的邏輯。迭代器是懶惰的,這意味著它們在調用消耗迭代器的方法之前沒有作用。

示例:

    let v1 = vec![1, 2, 3];let v1_iter = v1.iter();for val in v1_iter {println!("Got: {val}");}

在這個示例中,我們將迭代器的創建與在 for 循環中使用迭代器分開。當使用 v1_iter 中的迭代器調用 for 循環時,迭代器中的每個元素都會在循環的一次迭代中使用,并打印出每個值。

Iterator trait 和 next 方法

所有迭代器都實現一個名為 Iterator 的 trait,該 trait 在標準庫中定義。這個特性的定義是這樣的:

pub trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>;// methods with default implementations elided
}

注意,這個定義使用了一些新的語法:type Item 和 Self::Item,它們定義了與這個 trait 相關聯的類型。這段代碼表明,實現 Iterator trait 還需要定義一個 Item 類型,并且該 Item 類型用于下一個方法的返回類型。換句話說,Item 類型將是迭代器返回的類型。

Iterator trait 只需要實現者定義一個方法:next 方法,每次返回迭代器的一個項,包裝在 Some 中,迭代結束時返回 None。

我們可以直接在迭代器上調用 next 方法。下面的代碼演示了在 vector 創建的迭代器上重復調用 next 會返回哪些值。

    #[test]fn iterator_demonstration() {let v1 = vec![1, 2, 3];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);}

注意,我們需要將 v1_iter 設置為可變的:在迭代器上調用 next 方法會改變迭代器用于跟蹤其在序列中的位置的內部狀態,每次調用都會消耗迭代器中的一個項。

在使用 for 循環時,不需要將 v1_iter 設為可變的,因為循環在后臺獲取了 v1_iter 的所有權并使其可變。

還要注意,從調用 next 得到的值是對 vector 中值的不可變引用。iter 方法在不可變引用上生成一個迭代器。如果要創建一個接受 v1 的所有權并返回擁有的值的迭代器,可以調用 into_iter 方法。類似地,如果要在可變引用上迭代,可以調用 iter_mut 方法。

使用迭代器的方法

Iterator trait 有許多不同的方法,由標準庫提供默認實現。其中一些方法在其定義中調用 next 方法,這就是為什么在實現 Iterator trait 時需要實現 next 方法的原因。

調用 next 的方法稱為消費適配器,因為調用它們會耗盡迭代器。

一個例子是 sum 方法,它獲得迭代器的所有權,并通過重復調用 next 來遍歷項,從而消耗迭代器。當它遍歷時,它將每個項目添加到運行總數中,并在迭代完成時返回總數。

    #[test]fn iterator_sum() {let v1 = vec![1, 2, 3];let v1_iter = v1.iter();let total: i32 = v1_iter.sum();assert_eq!(total, 6);}

注意,在調用 sum 之后不允許使用 v1_iter,因為 sum 將獲得調用它的迭代器的所有權。

生成其他迭代器的方法

迭代器適配器是在 Iterator trait 上定義的不消耗迭代器的方法。相反,它們通過改變原始迭代器的某些方面來生成不同的迭代器。

下面代碼是調用迭代器適配器方法 map 的示例,該方法接受一個閉包,在遍歷每個項目時調用該閉包。map 方法返回一個新的迭代器,用于生成修改后的項。

    let v1: Vec<i32> = vec![1, 2, 3];v1.iter().map(|x| x + 1);

運行代碼會得到一個警告:我們指定的閉包永遠不會被調用。這個警告提醒了我們原因:迭代器適配器是惰性的,我們需要在這里消費迭代器。

在這里插入圖片描述

為了修復這個警告并消費迭代器,我們將使用 collect 方法,此方法使用迭代器并將結果值收集到集合數據類型中。

    let v1: Vec<i32> = vec![1, 2, 3];let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();assert_eq!(v2, vec![2, 3, 4]);

因為 map 接受閉包,所以可以指定想對每個項執行的任何操作。

還可以將多個調用鏈接到迭代器適配器,以可讀的方式執行復雜的操作。但是,由于所有迭代器都是惰性的,因此必須調用一個使用適配器的方法來從調用迭代器適配器中獲取結果。

使用閉包捕獲它們的環境

許多迭代器適配器將閉包作為參數,通常我們指定作為迭代器適配器參數的閉包將是捕獲其環境的閉包。

示例:

#[derive(PartialEq, Debug)]
struct Shoe {size: u32,style: String,
}fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}#[cfg(test)]
mod tests {use super::*;#[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_size(shoes, 10);assert_eq!(in_my_size,vec![Shoe {size: 10,style: String::from("sneaker")},Shoe {size: 10,style: String::from("boot")},]);}
}

對于本例,我們將使用接受閉包的 filter 方法。閉包從迭代器獲取一個元素并返回 bool 值。如果閉包返回 true,則該值將包含在 filter 生成的迭代器中。如果閉包返回 false,則不包含該值。

在 shoes_in_size 的函數體中,調用 into_iter 來創建一個接受 vector 對象所有權的迭代器。然后調用 filter 將該迭代器改編為一個新的迭代器。filter 方法的閉包從環境中捕獲 shoe_size 參數,并將其值與每只鞋的尺寸進行比較,只保留指定尺寸的鞋子。最后,調用 collect 將經過調整的迭代器返回的值收集到函數返回的向量中。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81774.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81774.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81774.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【深度剖析】義齒定制行業數字化轉型模式創新研究(上篇2:痛點和難點分析)

數字化轉型正在重塑義齒行業的生態格局,但也面臨技術融合與模式變革的深層挑戰。當前,義齒定制行業正處于從傳統手工制造向全流程數字化制造轉型的關鍵階段。3D掃描、CAD/CAM(計算機輔助設計與制造)、3D打印等技術的廣泛應用,顯著提升了義齒制作的精度和效率。傳統石膏模型…

window安裝nginx

步驟1&#xff1a;下載Nginx for Windows? 訪問Nginx官網下載頁面&#xff1a;https://nginx.org/en/download.html 在??Stable version??&#xff08;穩定版&#xff09;下找到Windows版本&#xff0c;點擊下載.zip文件&#xff08;如 nginx-1.28.0.zip&#xff09; 步…

氣象算法工程師學習路徑

目錄 &#x1f324;? 氣象學與數值預報基礎課程&#x1f916; 氣象人工智能與數據分析課程&#x1f4d8; 進階與實戰課程推薦&#x1f9ed; 學習建議與路徑規劃 如果希望成為一名氣象算法工程師&#xff0c;并尋找深入淺出、理論與實踐結合的學習資源&#xff0c;以下是為你精…

回調函數的理解

int yuxiangrousi 0; // 全局變量&#xff1a;魚香肉絲&#xff08;醬油量&#xff09;// 回調函數&#xff1a;媽媽處理醬油&#xff08;將醬油加入魚香肉絲&#xff09; void mother_callback(int new_jiangyou) {yuxiangrousi new_jiangyou; // 把醬油放進魚香肉絲 }// 孩…

多部手機連接同一wifi的ip一樣嗎?如何更改ip

通常情況下&#xff0c;多部手機連接同一個WiFi時&#xff0c;它們的IP地址是各不相同的&#xff08;在局域網內&#xff09;。但是&#xff0c;從互聯網&#xff08;外網&#xff09;的角度看&#xff0c;它們共享同一個公網IP地址。讓我詳細解釋一下&#xff0c;并說明如何更…

環境溫度通過H2A.Zub和H3K27me3動態調控擬南芥細胞命運決定

2025年4月22日&#xff0c;中國科學院遺傳與發育生物學研究所肖軍研究組在Developmental Cell在線發表了題為Dynamic control of H2A.Zub and H3K27me3 by ambient temperature during cell fate determination in Arabidopsis的研究論文&#xff0c;本研究綜合運用ChIP-seq、C…

2024 吉林 CCPC

文章目錄 2024 吉林 CCPCL. Recharge&#xff08;思維、分配&#xff09;G. Platform Game(模擬)E. Connect Components (排序、思維)D. Parallel Lines 2024 吉林 CCPC 題目鏈接&#xff1a; Dashboard - The 2024 CCPC National Invitational Contest (Changchun) , The 17…

day13 leetcode-hot100-24(鏈表3)

234. 回文鏈表 - 力扣&#xff08;LeetCode&#xff09; 1.轉化法 思路 將鏈表轉化為列表進行比較 復習到的知識 arraylist的長度函數&#xff1a;list.size() 具體代碼 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode ne…

Vim文本編輯器快捷鍵用法以及簡單介紹

目錄 vim文本編輯器 簡介&#xff1a; 語法&#xff1a; vim模式介紹&#xff1a; 模式切換&#xff1a; 用法&#xff1a; 編輯模式&#xff1a; 一般模式&#xff1a; 命令模式&#xff1a; vim文本編輯器 簡介&#xff1a; 在命令行界面下&#xff0c;最常用的文本…

從 0 到 1:Spring Boot 與 Spring AI 深度實戰(基于深度求索 DeepSeek)

在人工智能技術與企業級開發深度融合的今天&#xff0c;傳統軟件開發模式與 AI 工程化開發的差異日益顯著。作為 Spring 生態體系中專注于 AI 工程化的核心框架&#xff0c;Spring AI通過標準化集成方案大幅降低 AI 應用開發門檻。本文將以國產大模型代表 ** 深度求索&#xff…

[Windows] 摸魚小工具:隱藏軟件(重制版)

由吾愛大神寫的摸魚工具&#xff1a; 數據存放路徑為C:\Users\用戶名\AppData\Local\HideSoft&#xff0c;如果不想用時&#xff0c;刪除軟件及此路徑下的HideSoft文件夾。如添加了開機啟動&#xff0c;刪除啟動菜單文件夾的快捷方式即可&#xff0c;或者刪除前在軟件中取消設置…

C++ 判斷文件的編碼類型

大多數文本編輯器&#xff0c;都會在文本文件的頭部插入一部分特殊的字節&#xff0c;用于輔助文本編輯器來判斷該文件的字符集編碼類型。 如&#xff1a;記事本 目前支持的字符集類型&#xff0c;通常為三種&#xff1a; Unicode、UTF8、UnicodeBIG、CP_ACP&#xff08;默認…

時間序列噪聲模型分析軟件推薦與使用經驗

最近在論文大修2024年投稿的一篇文章&#xff0c;大修了2輪&#xff0c;最后一次還是重新投稿&#xff0c;其中有一個問題一直被審稿人懟&#xff0c;他認為我計算時間序列的趨勢的時候&#xff0c;沒有考慮時間的相關性&#xff0c;即對噪聲模型的估計不合理&#xff0c;會影響…

【redis實戰篇】第六天

摘要&#xff1a; 本文介紹了基于Redis的秒殺系統優化方案&#xff0c;主要包含兩部分&#xff1a;1&#xff09;通過Lua腳本校驗用戶秒殺資格&#xff0c;結合Java異步處理訂單提升性能&#xff1b;2&#xff09;使用Redis Stream實現消息隊列處理訂單。方案采用Lua腳本保證庫…

【Java Web】速通HTML

參考筆記: JavaWeb 速通HTML_java html頁面-CSDN博客 目錄 一、前言 1.網頁組成 1 結構 2 表現 3 行為 2.HTML入門 1 基本介紹 2 基本結構 3. HTML標簽 1 基本說明 2 注意事項 4. HTML概念名詞解釋 二、HTML常用標簽匯總 + 案例演示 1. 字體標簽 font (1)定義 (2)案例 2…

Oracle/openGauss中,DATE/TIMESTAMP與數字日期/字符日期比較

ORACLE 運行環境 openGauss 運行環境 0、前置知識 ORACLE&#xff1a;DUMP()函數用于返回指定表達式的數據類型、字節長度及內部存儲表示的詳細信息 SELECT DUMP(123) FROM DUAL; -- Typ2 Len3: 194,2,24 SELECT DUMP(123) FROM DUAL;-- Typ96 Len3: 49,50,51 -- ASCII值&am…

[學習]C++ 模板探討(代碼示例)

C 模板探討 文章目錄 C 模板探討一、模板基礎概念二、函數模板三、類模板1. 類模板的定義與使用2. 成員函數模板3. 類模板的靜態成員與繼承 四、模板進階特性1. 非類型模板參數2. 可變參數模板&#xff08;Variadic Templates&#xff09;3. 模板元編程&#xff08;TMP&#xf…

人工智能-訓練AI模型涉及多個步驟

訓練AI模型涉及多個步驟&#xff0c;包括數據預處理、選擇合適的模型、訓練模型以及評估模型性能。下面是一個詳細的流程&#xff0c;以常見的機器學習任務——分類問題為例&#xff0c;展示如何使用Python中的scikit-learn庫來訓練一個簡單的AI模型。 步驟 1: 導入所需的庫 …

LVS+Keepalived 高可用

目錄 一、核心概念 1. LVS&#xff08;Linux Virtual Server&#xff09; 2. Keepalived 二、高可用架構設計 1. 架構拓撲圖 2. 工作流程 三、部署步驟&#xff08;以 DR 模式為例&#xff09; 1. 環境準備 2. 主 LVS 節點配置 &#xff08;1&#xff09;安裝 Keepali…

TCP 三次握手過程詳解

TCP 三次握手過程詳解 一、TCP握手基礎概念 1.1 什么是TCP握手 TCP三次握手是傳輸控制協議(Transmission Control Protocol)在建立連接時的標準過程,目的是確保通信雙方具備可靠的雙向通信能力。 關鍵結論:三次握手的本質是通過序列號同步和能力協商建立可靠的邏輯連接。 …