-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathch13-02-iterators.html
204 lines (182 loc) · 75.6 KB
/
ch13-02-iterators.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>使用迭代器处理元素序列</title>
<meta name="generator" content="VuePress 1.5.3">
<meta name="description" content="">
<link rel="preload" href="/assets/css/0.styles.12e35fbb.css" as="style"><link rel="preload" href="/assets/js/app.e6b14c5e.js" as="script"><link rel="preload" href="/assets/js/3.ecc21787.js" as="script"><link rel="preload" href="/assets/js/1.032ec45e.js" as="script"><link rel="preload" href="/assets/js/76.ad390b83.js" as="script"><link rel="prefetch" href="/assets/js/10.0db432dd.js"><link rel="prefetch" href="/assets/js/100.1149107d.js"><link rel="prefetch" href="/assets/js/101.feae8ac2.js"><link rel="prefetch" href="/assets/js/102.4be35ad2.js"><link rel="prefetch" href="/assets/js/103.cb0bcc26.js"><link rel="prefetch" href="/assets/js/104.581a9df8.js"><link rel="prefetch" href="/assets/js/105.a5b31ce3.js"><link rel="prefetch" href="/assets/js/106.feb2cd4c.js"><link rel="prefetch" href="/assets/js/107.c74c3f7d.js"><link rel="prefetch" href="/assets/js/108.6a32c62d.js"><link rel="prefetch" href="/assets/js/109.3c3188fd.js"><link rel="prefetch" href="/assets/js/11.04463d2c.js"><link rel="prefetch" href="/assets/js/110.5f3f2327.js"><link rel="prefetch" href="/assets/js/111.374cf29b.js"><link rel="prefetch" href="/assets/js/112.37a66948.js"><link rel="prefetch" href="/assets/js/113.0e87d41d.js"><link rel="prefetch" href="/assets/js/114.e2641184.js"><link rel="prefetch" href="/assets/js/115.903cb5c3.js"><link rel="prefetch" href="/assets/js/116.d1cfad4c.js"><link rel="prefetch" href="/assets/js/117.ca412492.js"><link rel="prefetch" href="/assets/js/118.23919bb0.js"><link rel="prefetch" href="/assets/js/12.2de3af2e.js"><link rel="prefetch" href="/assets/js/13.69a23a33.js"><link rel="prefetch" href="/assets/js/14.3335c861.js"><link rel="prefetch" href="/assets/js/15.a469e71d.js"><link rel="prefetch" href="/assets/js/16.ee173d9e.js"><link rel="prefetch" href="/assets/js/17.959da5cf.js"><link rel="prefetch" href="/assets/js/18.0aa8fea6.js"><link rel="prefetch" href="/assets/js/19.21e6464d.js"><link rel="prefetch" href="/assets/js/20.b6d578fe.js"><link rel="prefetch" href="/assets/js/21.986be82f.js"><link rel="prefetch" href="/assets/js/22.47be6a63.js"><link rel="prefetch" href="/assets/js/23.15fe85eb.js"><link rel="prefetch" href="/assets/js/24.b3a04842.js"><link rel="prefetch" href="/assets/js/25.ae75ed87.js"><link rel="prefetch" href="/assets/js/26.643de6d4.js"><link rel="prefetch" href="/assets/js/27.6663d0a9.js"><link rel="prefetch" href="/assets/js/28.4669e096.js"><link rel="prefetch" href="/assets/js/29.65085b51.js"><link rel="prefetch" href="/assets/js/30.b4315895.js"><link rel="prefetch" href="/assets/js/31.e7ecf0dd.js"><link rel="prefetch" href="/assets/js/32.5d1db543.js"><link rel="prefetch" href="/assets/js/33.e8747222.js"><link rel="prefetch" href="/assets/js/34.852658b5.js"><link rel="prefetch" href="/assets/js/35.fa3f0352.js"><link rel="prefetch" href="/assets/js/36.8ebb5fa0.js"><link rel="prefetch" href="/assets/js/37.fa05856b.js"><link rel="prefetch" href="/assets/js/38.9aaa7af9.js"><link rel="prefetch" href="/assets/js/39.1a8b291e.js"><link rel="prefetch" href="/assets/js/4.f09c27b1.js"><link rel="prefetch" href="/assets/js/40.b9a756f6.js"><link rel="prefetch" href="/assets/js/41.7cef9fb3.js"><link rel="prefetch" href="/assets/js/42.04a2dfd5.js"><link rel="prefetch" href="/assets/js/43.b586e125.js"><link rel="prefetch" href="/assets/js/44.83db3147.js"><link rel="prefetch" href="/assets/js/45.e09151dc.js"><link rel="prefetch" href="/assets/js/46.f4d7d1f9.js"><link rel="prefetch" href="/assets/js/47.b935a8bb.js"><link rel="prefetch" href="/assets/js/48.10681e24.js"><link rel="prefetch" href="/assets/js/49.04036517.js"><link rel="prefetch" href="/assets/js/5.9229c7e7.js"><link rel="prefetch" href="/assets/js/50.385b0179.js"><link rel="prefetch" href="/assets/js/51.0a5c574d.js"><link rel="prefetch" href="/assets/js/52.5cd11b21.js"><link rel="prefetch" href="/assets/js/53.2efb9eb9.js"><link rel="prefetch" href="/assets/js/54.dd3a8f7d.js"><link rel="prefetch" href="/assets/js/55.e72498d3.js"><link rel="prefetch" href="/assets/js/56.5611b803.js"><link rel="prefetch" href="/assets/js/57.004dcc8a.js"><link rel="prefetch" href="/assets/js/58.de3a101d.js"><link rel="prefetch" href="/assets/js/59.a4d35b66.js"><link rel="prefetch" href="/assets/js/6.2ede05ad.js"><link rel="prefetch" href="/assets/js/60.ffa87f2b.js"><link rel="prefetch" href="/assets/js/61.c97c2157.js"><link rel="prefetch" href="/assets/js/62.1a964fd5.js"><link rel="prefetch" href="/assets/js/63.4fadefff.js"><link rel="prefetch" href="/assets/js/64.b0507c62.js"><link rel="prefetch" href="/assets/js/65.09fcdb27.js"><link rel="prefetch" href="/assets/js/66.c8f8a5cc.js"><link rel="prefetch" href="/assets/js/67.02fa33de.js"><link rel="prefetch" href="/assets/js/68.d49f848f.js"><link rel="prefetch" href="/assets/js/69.9dc909c1.js"><link rel="prefetch" href="/assets/js/7.00d72aac.js"><link rel="prefetch" href="/assets/js/70.e9702890.js"><link rel="prefetch" href="/assets/js/71.41a43a69.js"><link rel="prefetch" href="/assets/js/72.9f6f3145.js"><link rel="prefetch" href="/assets/js/73.64d032a1.js"><link rel="prefetch" href="/assets/js/74.6bb7d811.js"><link rel="prefetch" href="/assets/js/75.f9ddba21.js"><link rel="prefetch" href="/assets/js/77.bc150afb.js"><link rel="prefetch" href="/assets/js/78.69dc1271.js"><link rel="prefetch" href="/assets/js/79.5ce4cf53.js"><link rel="prefetch" href="/assets/js/8.f3a923c0.js"><link rel="prefetch" href="/assets/js/80.a9598d24.js"><link rel="prefetch" href="/assets/js/81.b1ca9b22.js"><link rel="prefetch" href="/assets/js/82.1017a114.js"><link rel="prefetch" href="/assets/js/83.d4fdce6e.js"><link rel="prefetch" href="/assets/js/84.f13715fe.js"><link rel="prefetch" href="/assets/js/85.af5497b5.js"><link rel="prefetch" href="/assets/js/86.07fb3684.js"><link rel="prefetch" href="/assets/js/87.d175c777.js"><link rel="prefetch" href="/assets/js/88.aa6d98dd.js"><link rel="prefetch" href="/assets/js/89.3d1bef74.js"><link rel="prefetch" href="/assets/js/9.3c7c9ecc.js"><link rel="prefetch" href="/assets/js/90.f46d49e9.js"><link rel="prefetch" href="/assets/js/91.6f0b514b.js"><link rel="prefetch" href="/assets/js/92.5a1abbdf.js"><link rel="prefetch" href="/assets/js/93.c50314c2.js"><link rel="prefetch" href="/assets/js/94.becb0d94.js"><link rel="prefetch" href="/assets/js/95.cc5ea7c4.js"><link rel="prefetch" href="/assets/js/96.1ba1f23b.js"><link rel="prefetch" href="/assets/js/97.0436550a.js"><link rel="prefetch" href="/assets/js/98.180142a4.js"><link rel="prefetch" href="/assets/js/99.fa82e156.js">
<link rel="stylesheet" href="/assets/css/0.styles.12e35fbb.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container" data-v-dad8a512><div data-v-dad8a512><div id="loader-wrapper" class="loading-wrapper" data-v-d48f4d20 data-v-dad8a512 data-v-dad8a512><div class="loader-main" data-v-d48f4d20><div data-v-d48f4d20></div><div data-v-d48f4d20></div><div data-v-d48f4d20></div><div data-v-d48f4d20></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-64685f0e data-v-dad8a512 data-v-dad8a512><h3 class="title" style="display:none;" data-v-64685f0e data-v-64685f0e></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-64685f0e data-v-64685f0e><input type="password" value="" data-v-64685f0e> <span data-v-64685f0e>Konck! Knock!</span> <button data-v-64685f0e>OK</button></label> <div class="footer" style="display:none;" data-v-64685f0e data-v-64685f0e><span data-v-64685f0e><i class="iconfont reco-theme" data-v-64685f0e></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-64685f0e>vuePress-theme-reco</a></span> <span data-v-64685f0e><i class="iconfont reco-copyright" data-v-64685f0e></i> <a data-v-64685f0e><!---->
<!---->
2020
</a></span></div></div> <div class="hide" data-v-dad8a512><header class="navbar" data-v-dad8a512><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont undefined"></i>
回首页
</a></div> <!----></nav></div></header> <div class="sidebar-mask" data-v-dad8a512></div> <aside class="sidebar" data-v-dad8a512><div class="personal-info-wrapper" data-v-ca798c94 data-v-dad8a512><!----> <!----> <div class="num" data-v-ca798c94><div data-v-ca798c94><h3 data-v-ca798c94>0</h3> <h6 data-v-ca798c94>Article</h6></div> <div data-v-ca798c94><h3 data-v-ca798c94>0</h3> <h6 data-v-ca798c94>Tag</h6></div></div> <hr data-v-ca798c94></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont undefined"></i>
回首页
</a></div> <!----></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><a href="/title-page" class="sidebar-heading clickable open"><span>Rust 程序设计语言</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/foreword.html" class="sidebar-link">前言</a></li><li><a href="/ch00-00-introduction.html" class="sidebar-link">介绍</a></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch01-00-getting-started.html" class="sidebar-heading clickable"><span>1. 入门指南</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch01-01-installation.html" class="sidebar-link">1.1. 安装</a></li><li><a href="/ch01-02-hello-world.html" class="sidebar-link">1.2. Hello, World!</a></li><li><a href="/ch01-03-hello-cargo.html" class="sidebar-link">1.3. Hello, Cargo!</a></li></ul></section></li><li><a href="/ch02-00-guessing-game-tutorial.html" class="sidebar-link">2. 猜猜看游戏教程</a></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch03-00-common-programming-concepts.html" class="sidebar-heading clickable"><span>3. 常见编程概念</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch03-01-variables-and-mutability.html" class="sidebar-link">3.1. 变量与可变性</a></li><li><a href="/ch03-02-data-types.html" class="sidebar-link">3.2. 数据类型</a></li><li><a href="/ch03-03-how-functions-work.html" class="sidebar-link">3.3. 函数如何工作</a></li><li><a href="/ch03-04-comments.html" class="sidebar-link">3.4. 注释</a></li><li><a href="/ch03-05-control-flow.html" class="sidebar-link">3.5. 控制流</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch04-00-understanding-ownership.html" class="sidebar-heading clickable"><span>4. 认识所有权</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch04-01-what-is-ownership.html" class="sidebar-link">4.1. 什么是所有权?</a></li><li><a href="/ch04-02-references-and-borrowing.html" class="sidebar-link">4.2. 引用与借用</a></li><li><a href="/ch04-03-slices.html" class="sidebar-link">4.3. Slices</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch05-00-structs.html" class="sidebar-heading clickable"><span>5. 使用结构体来组织相关联的数据</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch05-01-defining-structs.html" class="sidebar-link">5.1. 定义并实例化结构体</a></li><li><a href="/ch05-02-example-structs.html" class="sidebar-link">5.2. 一个使用结构体的示例程序</a></li><li><a href="/ch05-03-method-syntax.html" class="sidebar-link">5.3. 方法语法</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch06-00-enums.html" class="sidebar-heading clickable"><span>6. 枚举与模式匹配</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch06-01-defining-an-enum.html" class="sidebar-link">6.1. 定义枚举</a></li><li><a href="/ch06-02-match.html" class="sidebar-link">6.2. match控制流运算符</a></li><li><a href="/ch06-03-if-let.html" class="sidebar-link">6.3. if let简洁控制流</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html" class="sidebar-heading clickable"><span>7. 使用包、Crate 和模块管理不断增长的项目</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch07-01-packages-and-crates.html" class="sidebar-link">7.1. 包和 crate</a></li><li><a href="/ch07-02-defining-modules-to-control-scope-and-privacy.html" class="sidebar-link">7.2. 定义模块来控制作用域与私有性</a></li><li><a href="/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html" class="sidebar-link">7.3. 路径用于引用模块树中的项</a></li><li><a href="/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html" class="sidebar-link">7.4. 使用use关键字将名称引入作用域</a></li><li><a href="/ch07-05-separating-modules-into-different-files.html" class="sidebar-link">7.5. 将模块分割进不同文件</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch08-00-common-collections.html" class="sidebar-heading clickable"><span>8. 常见集合</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch08-01-vectors.html" class="sidebar-link">8.1. vector</a></li><li><a href="/ch08-02-strings.html" class="sidebar-link">8.2. 字符串</a></li><li><a href="/ch08-03-hash-maps.html" class="sidebar-link">8.3. 哈希 map</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch09-00-error-handling.html" class="sidebar-heading clickable"><span>9. 错误处理</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch09-01-unrecoverable-errors-with-panic.html" class="sidebar-link">9.1. panic!与不可恢复的错误</a></li><li><a href="/ch09-02-recoverable-errors-with-result.html" class="sidebar-link">9.2. Result与可恢复的错误</a></li><li><a href="/ch09-03-to-panic-or-not-to-panic.html" class="sidebar-link">9.3. panic!还是不panic!</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch10-00-generics.html" class="sidebar-heading clickable"><span>10. 泛型、trait 与生命周期</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch10-01-syntax.html" class="sidebar-link">10.1. 泛型数据类型</a></li><li><a href="/ch10-02-traits.html" class="sidebar-link">10.2. trait:定义共享的行为</a></li><li><a href="/ch10-03-lifetime-syntax.html" class="sidebar-link">10.3. 生命周期与引用有效性</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch11-00-testing.html" class="sidebar-heading clickable"><span>11. 测试</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch11-01-writing-tests.html" class="sidebar-link">11.1. 编写测试</a></li><li><a href="/ch11-02-running-tests.html" class="sidebar-link">11.2. 运行测试</a></li><li><a href="/ch11-03-test-organization.html" class="sidebar-link">11.3. 测试的组织结构</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch12-00-an-io-project.html" class="sidebar-heading clickable"><span>12. 一个 I/O 项目:构建命令行程序</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch12-01-accepting-command-line-arguments.html" class="sidebar-link">12.1. 接受命令行参数</a></li><li><a href="/ch12-02-reading-a-file.html" class="sidebar-link">12.2. 读取文件</a></li><li><a href="/ch12-03-improving-error-handling-and-modularity.html" class="sidebar-link">12.3. 重构以改进模块化与错误处理</a></li><li><a href="/ch12-04-testing-the-librarys-functionality.html" class="sidebar-link">12.4. 采用测试驱动开发完善库的功能</a></li><li><a href="/ch12-05-working-with-environment-variables.html" class="sidebar-link">12.5. 处理环境变量</a></li><li><a href="/ch12-06-writing-to-stderr-instead-of-stdout.html" class="sidebar-link">12.6. 将错误信息输出到标准错误而不是标准输出</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch13-00-functional-features.html" class="sidebar-heading clickable open"><span>13. Rust 中的函数式语言功能:迭代器与闭包</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch13-01-closures.html" class="sidebar-link">13.1. 闭包:可以捕获其环境的匿名函数</a></li><li><a href="/ch13-02-iterators.html" aria-current="page" class="active sidebar-link">13.2. 使用迭代器处理元素序列</a></li><li><a href="/ch13-03-improving-our-io-project.html" class="sidebar-link">13.3. 改进之前的 I/O 项目</a></li><li><a href="/ch13-04-performance.html" class="sidebar-link">13.4. 性能比较:循环对迭代器</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch14-00-more-about-cargo.html" class="sidebar-heading clickable"><span>14. 更多关于 Cargo 和 Crates.io 的内容</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch14-01-release-profiles.html" class="sidebar-link">14.1. 采用发布配置自定义构建</a></li><li><a href="/ch14-02-publishing-to-crates-io.html" class="sidebar-link">14.2. 将 crate 发布到 Crates.io</a></li><li><a href="/ch14-03-cargo-workspaces.html" class="sidebar-link">14.3. Cargo 工作空间</a></li><li><a href="/ch14-04-installing-binaries.html" class="sidebar-link">14.4. 使用cargo install从 Crates.io 安装二进制文件</a></li><li><a href="/ch14-05-extending-cargo.html" class="sidebar-link">14.5. Cargo 自定义扩展命令</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch15-00-smart-pointers.html" class="sidebar-heading clickable"><span>15. 智能指针</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch15-01-box.html" class="sidebar-link">15.1. Box<T>指向堆上数据,并且可确定大小</a></li><li><a href="/ch15-02-deref.html" class="sidebar-link">15.2. 通过Dereftrait 将智能指针当作常规引用处理</a></li><li><a href="/ch15-03-drop.html" class="sidebar-link">15.3. DropTrait 运行清理代码</a></li><li><a href="/ch15-04-rc.html" class="sidebar-link">15.4. Rc<T>引用计数智能指针</a></li><li><a href="/ch15-05-interior-mutability.html" class="sidebar-link">15.5. RefCell<T>与内部可变性模式</a></li><li><a href="/ch15-06-reference-cycles.html" class="sidebar-link">15.6. 引用循环与内存泄漏是安全的</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch16-00-concurrency.html" class="sidebar-heading clickable"><span>16. 无畏并发</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch16-01-threads.html" class="sidebar-link">16.1. 线程</a></li><li><a href="/ch16-02-message-passing.html" class="sidebar-link">16.2. 消息传递</a></li><li><a href="/ch16-03-shared-state.html" class="sidebar-link">16.3. 共享状态</a></li><li><a href="/ch16-04-extensible-concurrency-sync-and-send.html" class="sidebar-link">16.4. 可扩展的并发:Sync与Send</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch17-00-oop.html" class="sidebar-heading clickable"><span>17. Rust 的面向对象编程特性</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch17-01-what-is-oo.html" class="sidebar-link">17.1. 面向对象语言的特点</a></li><li><a href="/ch17-02-trait-objects.html" class="sidebar-link">17.2. 为使用不同类型的值而设计的 trait 对象</a></li><li><a href="/ch17-03-oo-design-patterns.html" class="sidebar-link">17.3. 面向对象设计模式的实现</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch18-00-patterns.html" class="sidebar-heading clickable"><span>18. 模式用来匹配值的结构</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch18-01-all-the-places-for-patterns.html" class="sidebar-link">18.1. 所有可能会用到模式的位置</a></li><li><a href="/ch18-02-refutability.html" class="sidebar-link">18.2. Refutability:何时模式可能会匹配失败</a></li><li><a href="/ch18-03-pattern-syntax.html" class="sidebar-link">18.3. 模式的全部语法</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch19-00-advanced-features.html" class="sidebar-heading clickable"><span>19. 高级特征</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch19-01-unsafe-rust.html" class="sidebar-link">19.1. 不安全的 Rust</a></li><li><a href="/ch19-03-advanced-traits.html" class="sidebar-link">19.2. 高级 trait</a></li><li><a href="/ch19-04-advanced-types.html" class="sidebar-link">19.3. 高级类型</a></li><li><a href="/ch19-05-advanced-functions-and-closures.html" class="sidebar-link">19.4. 高级函数与闭包</a></li><li><a href="/ch19-06-macros.html" class="sidebar-link">19.5. 宏</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/ch20-00-final-project-a-web-server.html" class="sidebar-heading clickable"><span>20. 最后的项目: 构建多线程 web server</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/ch20-01-single-threaded.html" class="sidebar-link">20.1. 单线程 web server</a></li><li><a href="/ch20-02-multithreaded.html" class="sidebar-link">20.2. 将单线程 server 变为多线程 server</a></li><li><a href="/ch20-03-graceful-shutdown-and-cleanup.html" class="sidebar-link">20.3. 优雅停机与清理</a></li></ul></section></li><li><section class="sidebar-group is-sub-group depth-1"><a href="/appendix-00.html" class="sidebar-heading clickable"><span>21. 附录</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/appendix-01-keywords.html" class="sidebar-link">21.1. A - 关键字</a></li><li><a href="/appendix-02-operators.html" class="sidebar-link">21.2. B - 运算符与符号</a></li><li><a href="/appendix-03-derivable-traits.html" class="sidebar-link">21.3. C - 可派生的 trait</a></li><li><a href="/appendix-04-useful-development-tools.html" class="sidebar-link">21.4. D - 实用开发工具</a></li><li><a href="/appendix-05-editions.html" class="sidebar-link">21.5. E - 版本</a></li><li><a href="/appendix-06-translation.html" class="sidebar-link">21.6. F - 本书译本</a></li><li><a href="/appendix-07-nightly-rust.html" class="sidebar-link">21.7. G - Rust 是如何开发的与 “Nightly Rust”</a></li></ul></section></li></ul></section></li></ul> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-64685f0e data-v-dad8a512><h3 class="title" style="display:none;" data-v-64685f0e data-v-64685f0e></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-64685f0e data-v-64685f0e><input type="password" value="" data-v-64685f0e> <span data-v-64685f0e>Konck! Knock!</span> <button data-v-64685f0e>OK</button></label> <div class="footer" style="display:none;" data-v-64685f0e data-v-64685f0e><span data-v-64685f0e><i class="iconfont reco-theme" data-v-64685f0e></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-64685f0e>vuePress-theme-reco</a></span> <span data-v-64685f0e><i class="iconfont reco-copyright" data-v-64685f0e></i> <a data-v-64685f0e><!---->
<!---->
2020
</a></span></div></div> <div data-v-dad8a512><main class="page"><div class="page-title" style="display:none;"><h1>使用迭代器处理元素序列</h1> <div data-v-3b7f5bdf><!----> <!----> <!----> <!----></div></div> <div class="theme-reco-content content__default" style="display:none;"><h2 id="使用迭代器处理元素序列"><a href="#使用迭代器处理元素序列" class="header-anchor">#</a> 使用迭代器处理元素序列</h2> <blockquote><p><a href="https://github.com/rust-lang/book/blob/master/src/ch13-02-iterators.md" target="_blank" rel="noopener noreferrer">ch13-02-iterators.md<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> <br>
commit 8edf0457ab571b375b87357e1353ae0dd2127abe</p></blockquote> <p>迭代器模式允许你对一个项的序列进行某些处理。<strong>迭代器</strong>(<em>iterator</em>)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。</p> <p>在 Rust 中,迭代器是 <strong>惰性的</strong>(<em>lazy</em>),这意味着在调用方法使用迭代器之前它都不会有效果。例如,示例 13-13 中的代码通过调用定义于 <code>Vec</code> 上的 <code>iter</code> 方法在一个 vector <code>v1</code> 上创建了一个迭代器。这段代码本身没有任何用处:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> v1 <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> v1_iter <span class="token operator">=</span> v1<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><span class="caption">示例 13-13:创建一个迭代器</span></p> <p>一旦创建迭代器之后,可以选择用多种方式利用它。在第三章的示例 3-5 中,我们使用迭代器和 <code>for</code> 循环在每一个项上执行了一些代码,虽然直到现在为止我们一直没有具体讨论调用 <code>iter</code> 到底具体做了什么。</p> <p>示例 13-14 中的例子将迭代器的创建和 <code>for</code> 循环中的使用分开。迭代器被储存在 <code>v1_iter</code> 变量中,而这时没有进行迭代。一旦 <code>for</code> 循环开始使用 <code>v1_iter</code>,接着迭代器中的每一个元素被用于循环的一次迭代,这会打印出其每一个值:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> v1 <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> v1_iter <span class="token operator">=</span> v1<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> val <span class="token keyword">in</span> v1_iter <span class="token punctuation">{</span>
<span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Got: {}"</span><span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-14:在一个 <code>for</code> 循环中使用迭代器</span></p> <p>在标准库中没有提供迭代器的语言中,我们可能会使用一个从 0 开始的索引变量,使用这个变量索引 vector 中的值,并循环增加其值直到达到 vector 的元素数量。</p> <p>迭代器为我们处理了所有这些逻辑,这减少了重复代码并消除了潜在的混乱。另外,迭代器的实现方式提供了对多种不同的序列使用相同逻辑的灵活性,而不仅仅是像 vector 这样可索引的数据结构.让我们看看迭代器是如何做到这些的。</p> <h3 id="iterator-trait-和-next-方法"><a href="#iterator-trait-和-next-方法" class="header-anchor">#</a> <code>Iterator</code> trait 和 <code>next</code> 方法</h3> <p>迭代器都实现了一个叫做 <code>Iterator</code> 的定义于标准库的 trait。这个 trait 的定义看起来像这样:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Iterator</span> <span class="token punctuation">{</span>
<span class="token keyword">type</span> <span class="token class-name">Item</span><span class="token punctuation">;</span>
<span class="token keyword">fn</span> <span class="token function-definition function">next</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Option</span><span class="token operator"><</span><span class="token keyword">Self</span><span class="token punctuation">::</span><span class="token class-name">Item</span><span class="token operator">></span><span class="token punctuation">;</span>
<span class="token comment">// 此处省略了方法的默认实现</span>
<span class="token punctuation">}</span>
</code></pre></div><p>注意这里有一下我们还未讲到的新语法:<code>type Item</code> 和 <code>Self::Item</code>,他们定义了 trait 的 <strong>关联类型</strong>(<em>associated type</em>)。第十九章会深入讲解关联类型,不过现在只需知道这段代码表明实现 <code>Iterator</code> trait 要求同时定义一个 <code>Item</code> 类型,这个 <code>Item</code> 类型被用作 <code>next</code> 方法的返回值类型。换句话说,<code>Item</code> 类型将是迭代器返回元素的类型。</p> <p><code>next</code> 是 <code>Iterator</code> 实现者被要求定义的唯一方法。<code>next</code> 一次返回迭代器中的一个项,封装在 <code>Some</code> 中,当迭代器结束时,它返回 <code>None</code>。</p> <p>可以直接调用迭代器的 <code>next</code> 方法;示例 13-15 有一个测试展示了重复调用由 vector 创建的迭代器的 <code>next</code> 方法所得到的值:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[test]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">iterator_demonstration</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> v1 <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> v1_iter <span class="token operator">=</span> v1<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>v1_iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>v1_iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>v1_iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>v1_iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">None</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-15:在迭代器上(直接)调用 <code>next</code> 方法</span></p> <p>注意 <code>v1_iter</code> 需要是可变的:在迭代器上调用 <code>next</code> 方法改变了迭代器中用来记录序列位置的状态。换句话说,代码 <strong>消费</strong>(consume)了,或使用了迭代器。每一个 <code>next</code> 调用都会从迭代器中消费一个项。使用 <code>for</code> 循环时无需使 <code>v1_iter</code> 可变因为 <code>for</code> 循环会获取 <code>v1_iter</code> 的所有权并在后台使 <code>v1_iter</code> 可变。</p> <p>另外需要注意到从 <code>next</code> 调用中得到的值是 vector 的不可变引用。<code>iter</code> 方法生成一个不可变引用的迭代器。如果我们需要一个获取 <code>v1</code> 所有权并返回拥有所有权的迭代器,则可以调用 <code>into_iter</code> 而不是 <code>iter</code>。类似的,如果我们希望迭代可变引用,则可以调用 <code>iter_mut</code> 而不是 <code>iter</code>。</p> <h3 id="消费迭代器的方法"><a href="#消费迭代器的方法" class="header-anchor">#</a> 消费迭代器的方法</h3> <p><code>Iterator</code> trait 有一系列不同的由标准库提供默认实现的方法;你可以在 <code>Iterator</code> trait 的标准库 API 文档中找到所有这些方法。一些方法在其定义中调用了 <code>next</code> 方法,这也就是为什么在实现 <code>Iterator</code> trait 时要求实现 <code>next</code> 方法的原因。</p> <p>这些调用 <code>next</code> 方法的方法被称为 <strong>消费适配器</strong>(<em>consuming adaptors</em>),因为调用他们会消耗迭代器。一个消费适配器的例子是 <code>sum</code> 方法。这个方法获取迭代器的所有权并反复调用 <code>next</code> 来遍历迭代器,因而会消费迭代器。当其遍历每一个项时,它将每一个项加总到一个总和并在迭代完成时返回总和。示例 13-16 有一个展示 <code>sum</code> 方法使用的测试:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[test]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">iterator_sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> v1 <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> v1_iter <span class="token operator">=</span> v1<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> total<span class="token punctuation">:</span> <span class="token keyword">i32</span> <span class="token operator">=</span> v1_iter<span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>total<span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-16:调用 <code>sum</code> 方法获取迭代器所有项的总和</span></p> <p>调用 <code>sum</code> 之后不再允许使用 <code>v1_iter</code> 因为调用 <code>sum</code> 时它会获取迭代器的所有权。</p> <h3 id="产生其他迭代器的方法"><a href="#产生其他迭代器的方法" class="header-anchor">#</a> 产生其他迭代器的方法</h3> <p><code>Iterator</code> trait 中定义了另一类方法,被称为 <strong>迭代器适配器</strong>(<em>iterator adaptors</em>),他们允许我们将当前迭代器变为不同类型的迭代器。可以链式调用多个迭代器适配器。不过因为所有的迭代器都是惰性的,必须调用一个消费适配器方法以便获取迭代器适配器调用的结果。</p> <p>示例 13-17 展示了一个调用迭代器适配器方法 <code>map</code> 的例子,该 <code>map</code> 方法使用闭包来调用每个元素以生成新的迭代器。 这里的闭包创建了一个新的迭代器,对其中 vector 中的每个元素都被加 1。不过这些代码会产生一个警告:</p> <p><span class="filename">文件名: src/main.rs</span></p> <div class="language-rust,not_desired_behavior extra-class"><pre class="language-text"><code>let v1: Vec<i32> = vec![1, 2, 3];
v1.iter().map(|x| x + 1);
</code></pre></div><p><span class="caption">示例 13-17:调用迭代器适配器 <code>map</code> 来创建一个新迭代器</span></p> <p>得到的警告是:</p> <div class="language-text extra-class"><pre class="language-text"><code>warning: unused `std::iter::Map` which must be used: iterator adaptors are lazy
and do nothing unless consumed
--> src/main.rs:4:5
|
4 | v1.iter().map(|x| x + 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
</code></pre></div><p>示例 13-17 中的代码实际上并没有做任何事;所指定的闭包从未被调用过。警告提醒了我们为什么:迭代器适配器是惰性的,而这里我们需要消费迭代器。</p> <p>为了修复这个警告并消费迭代器获取有用的结果,我们将使用第十二章示例 12-1 结合 <code>env::args</code> 使用的 <code>collect</code> 方法。这个方法消费迭代器并将结果收集到一个数据结构中。</p> <p>在示例 13-18 中,我们将遍历由 <code>map</code> 调用生成的迭代器的结果收集到一个 vector 中,它将会含有原始 vector 中每个元素加 1 的结果:</p> <p><span class="filename">文件名: src/main.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> v1<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator"><</span><span class="token keyword">i32</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> v2<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator"><</span>_<span class="token operator">></span> <span class="token operator">=</span> v1<span class="token punctuation">.</span><span class="token function">iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>x<span class="token closure-punctuation punctuation">|</span></span> x <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>v2<span class="token punctuation">,</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><span class="caption">示例 13-18:调用 <code>map</code> 方法创建一个新迭代器,接着调用 <code>collect</code> 方法消费新迭代器并创建一个 vector</span></p> <p>因为 <code>map</code> 获取一个闭包,可以指定任何希望在遍历的每个元素上执行的操作。这是一个展示如何使用闭包来自定义行为同时又复用 <code>Iterator</code> trait 提供的迭代行为的绝佳例子。</p> <h3 id="使用闭包获取环境"><a href="#使用闭包获取环境" class="header-anchor">#</a> 使用闭包获取环境</h3> <p>现在我们介绍了迭代器,让我们展示一个通过使用 <code>filter</code> 迭代器适配器和捕获环境的闭包的常规用例。迭代器的 <code>filter</code> 方法获取一个使用迭代器的每一个项并返回布尔值的闭包。如果闭包返回 <code>true</code>,其值将会包含在 <code>filter</code> 提供的新迭代器中。如果闭包返回 <code>false</code>,其值不会包含在结果迭代器中。</p> <p>示例 13-19 展示了使用 <code>filter</code> 和一个捕获环境中变量 <code>shoe_size</code> 的闭包,这样闭包就可以遍历一个 <code>Shoe</code> 结构体集合以便只返回指定大小的鞋子:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[derive(PartialEq, Debug)]</span>
<span class="token keyword">struct</span> <span class="token type-definition class-name">Shoe</span> <span class="token punctuation">{</span>
size<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token keyword">fn</span> <span class="token function-definition function">shoes_in_my_size</span><span class="token punctuation">(</span>shoes<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator"><</span><span class="token class-name">Shoe</span><span class="token operator">></span><span class="token punctuation">,</span> shoe_size<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Vec</span><span class="token operator"><</span><span class="token class-name">Shoe</span><span class="token operator">></span> <span class="token punctuation">{</span>
shoes<span class="token punctuation">.</span><span class="token function">into_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>s<span class="token closure-punctuation punctuation">|</span></span> s<span class="token punctuation">.</span>size <span class="token operator">==</span> shoe_size<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token attribute attr-name">#[test]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">filters_by_size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> shoes <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span>
<span class="token class-name">Shoe</span> <span class="token punctuation">{</span> size<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"sneaker"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Shoe</span> <span class="token punctuation">{</span> size<span class="token punctuation">:</span> <span class="token number">13</span><span class="token punctuation">,</span> style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"sandal"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Shoe</span> <span class="token punctuation">{</span> size<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"boot"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> in_my_size <span class="token operator">=</span> <span class="token function">shoes_in_my_size</span><span class="token punctuation">(</span>shoes<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>
in_my_size<span class="token punctuation">,</span>
<span class="token macro property">vec!</span><span class="token punctuation">[</span>
<span class="token class-name">Shoe</span> <span class="token punctuation">{</span> size<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"sneaker"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Shoe</span> <span class="token punctuation">{</span> size<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> style<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"boot"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-19:使用 <code>filter</code> 方法和一个捕获 <code>shoe_size</code> 的闭包</span></p> <p><code>shoes_in_my_size</code> 函数获取一个鞋子 vector 的所有权和一个鞋子大小作为参数。它返回一个只包含指定大小鞋子的 vector。</p> <p><code>shoes_in_my_size</code> 函数体中调用了 <code>into_iter</code> 来创建一个获取 vector 所有权的迭代器。接着调用 <code>filter</code> 将这个迭代器适配成一个只含有那些闭包返回 <code>true</code> 的元素的新迭代器。</p> <p>闭包从环境中捕获了 <code>shoe_size</code> 变量并使用其值与每一只鞋的大小作比较,只保留指定大小的鞋子。最终,调用 <code>collect</code> 将迭代器适配器返回的值收集进一个 vector 并返回。</p> <p>这个测试展示当调用 <code>shoes_in_my_size</code> 时,我们只会得到与指定值相同大小的鞋子。</p> <h3 id="实现-iterator-trait-来创建自定义迭代器"><a href="#实现-iterator-trait-来创建自定义迭代器" class="header-anchor">#</a> 实现 <code>Iterator</code> trait 来创建自定义迭代器</h3> <p>我们已经展示了可以通过在 vector 上调用 <code>iter</code>、<code>into_iter</code> 或 <code>iter_mut</code> 来创建一个迭代器。也可以用标准库中其他的集合类型创建迭代器,比如哈希 map。另外,可以实现 <code>Iterator</code> trait 来创建任何我们希望的迭代器。正如之前提到的,定义中唯一要求提供的方法就是 <code>next</code> 方法。一旦定义了它,就可以使用所有其他由 <code>Iterator</code> trait 提供的拥有默认实现的方法来创建自定义迭代器了!</p> <p>作为展示,让我们创建一个只会从 1 数到 5 的迭代器。首先,创建一个结构体来存放一些值,接着实现 <code>Iterator</code> trait 将这个结构体放入迭代器中并在此实现中使用其值。</p> <p>示例 13-20 有一个 <code>Counter</code> 结构体定义和一个创建 <code>Counter</code> 实例的关联函数 <code>new</code>:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">struct</span> <span class="token type-definition class-name">Counter</span> <span class="token punctuation">{</span>
count<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token keyword">impl</span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
<span class="token keyword">fn</span> <span class="token function-definition function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
<span class="token class-name">Counter</span> <span class="token punctuation">{</span> count<span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-20:定义 <code>Counter</code> 结构体和一个创建 <code>count</code> 初值为 0 的 <code>Counter</code> 实例的 <code>new</code> 函数</span></p> <p><code>Counter</code> 结构体有一个字段 <code>count</code>。这个字段存放一个 <code>u32</code> 值,它会记录处理 1 到 5 的迭代过程中的位置。<code>count</code> 是私有的因为我们希望 <code>Counter</code> 的实现来管理这个值。<code>new</code> 函数通过总是从为 0 的 <code>count</code> 字段开始新实例来确保我们需要的行为。</p> <p>接下来将为 <code>Counter</code> 类型实现 <code>Iterator</code> trait,通过定义 <code>next</code> 方法来指定使用迭代器时的行为,如示例 13-21 所示:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code># <span class="token keyword">struct</span> <span class="token type-definition class-name">Counter</span> <span class="token punctuation">{</span>
# count<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
# <span class="token punctuation">}</span>
#
<span class="token keyword">impl</span> <span class="token class-name">Iterator</span> <span class="token keyword">for</span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
<span class="token keyword">type</span> <span class="token class-name">Item</span> <span class="token operator">=</span> <span class="token keyword">u32</span><span class="token punctuation">;</span>
<span class="token keyword">fn</span> <span class="token function-definition function">next</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Option</span><span class="token operator"><</span><span class="token keyword">Self</span><span class="token punctuation">::</span><span class="token class-name">Item</span><span class="token operator">></span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator"><</span> <span class="token number">6</span> <span class="token punctuation">{</span>
<span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">.</span>count<span class="token punctuation">)</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token class-name">None</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-21:在 <code>Counter</code> 结构体上实现 <code>Iterator</code> trait</span></p> <p>这里将迭代器的关联类型 <code>Item</code> 设置为 <code>u32</code>,意味着迭代器会返回 <code>u32</code> 值集合。再一次,这里仍无需担心关联类型,第十九章会讲到。</p> <p>我们希望迭代器对其内部状态加一,这也就是为何将 <code>count</code> 初始化为 0:我们希望迭代器首先返回 1。如果 <code>count</code> 值小于 6,<code>next</code> 会返回封装在 <code>Some</code> 中的当前值,不过如果 <code>count</code> 大于或等于 6,迭代器会返回 <code>None</code>。</p> <h4 id="使用-counter-迭代器的-next-方法"><a href="#使用-counter-迭代器的-next-方法" class="header-anchor">#</a> 使用 <code>Counter</code> 迭代器的 <code>next</code> 方法</h4> <p>一旦实现了 <code>Iterator</code> trait,我们就有了一个迭代器!示例 13-22 展示了一个测试用来演示使用 <code>Counter</code> 结构体的迭代器功能,通过直接调用 <code>next</code> 方法,正如示例 13-15 中从 vector 创建的迭代器那样:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code># <span class="token keyword">struct</span> <span class="token type-definition class-name">Counter</span> <span class="token punctuation">{</span>
# count<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
# <span class="token punctuation">}</span>
#
# <span class="token keyword">impl</span> <span class="token class-name">Iterator</span> <span class="token keyword">for</span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
# <span class="token keyword">type</span> <span class="token class-name">Item</span> <span class="token operator">=</span> <span class="token keyword">u32</span><span class="token punctuation">;</span>
#
# <span class="token keyword">fn</span> <span class="token function-definition function">next</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Option</span><span class="token operator"><</span><span class="token keyword">Self</span><span class="token punctuation">::</span><span class="token class-name">Item</span><span class="token operator">></span> <span class="token punctuation">{</span>
# <span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
#
# <span class="token keyword">if</span> <span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator"><</span> <span class="token number">6</span> <span class="token punctuation">{</span>
# <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">.</span>count<span class="token punctuation">)</span>
# <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
# <span class="token class-name">None</span>
# <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
#
<span class="token attribute attr-name">#[test]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">calling_next_directly</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> counter <span class="token operator">=</span> <span class="token class-name">Counter</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span>counter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">None</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-22:测试 <code>next</code> 方法实现的功能</span></p> <p>这个测试在 <code>counter</code> 变量中新建了一个 <code>Counter</code> 实例并接着反复调用 <code>next</code> 方法,来验证我们实现的行为符合这个迭代器返回从 1 到 5 的值的预期。</p> <h4 id="使用自定义迭代器中其他-iterator-trait-方法"><a href="#使用自定义迭代器中其他-iterator-trait-方法" class="header-anchor">#</a> 使用自定义迭代器中其他 <code>Iterator</code> trait 方法</h4> <p>通过定义 <code>next</code> 方法实现 <code>Iterator</code> trait,我们现在就可以使用任何标准库定义的拥有默认实现的 <code>Iterator</code> trait 方法了,因为他们都使用了 <code>next</code> 方法的功能。</p> <p>例如,出于某种原因我们希望获取 <code>Counter</code> 实例产生的值,将这些值与另一个 <code>Counter</code> 实例在省略了第一个值之后产生的值配对,将每一对值相乘,只保留那些可以被三整除的结果,然后将所有保留的结果相加,这可以如示例 13-23 中的测试这样做:</p> <p><span class="filename">文件名: src/lib.rs</span></p> <div class="language-rust extra-class"><pre class="language-rust"><code># <span class="token keyword">struct</span> <span class="token type-definition class-name">Counter</span> <span class="token punctuation">{</span>
# count<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
# <span class="token punctuation">}</span>
#
# <span class="token keyword">impl</span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
# <span class="token keyword">fn</span> <span class="token function-definition function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
# <span class="token class-name">Counter</span> <span class="token punctuation">{</span> count<span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
#
# <span class="token keyword">impl</span> <span class="token class-name">Iterator</span> <span class="token keyword">for</span> <span class="token class-name">Counter</span> <span class="token punctuation">{</span>
# <span class="token comment">// 迭代器会产生 u32s</span>
# <span class="token keyword">type</span> <span class="token class-name">Item</span> <span class="token operator">=</span> <span class="token keyword">u32</span><span class="token punctuation">;</span>
#
# <span class="token keyword">fn</span> <span class="token function-definition function">next</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Option</span><span class="token operator"><</span><span class="token keyword">Self</span><span class="token punctuation">::</span><span class="token class-name">Item</span><span class="token operator">></span> <span class="token punctuation">{</span>
# <span class="token comment">// count 自增 1。也就是为什么从 0 开始。</span>
# <span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
#
# <span class="token comment">// 检测是否结束结束计数。</span>
# <span class="token keyword">if</span> <span class="token keyword">self</span><span class="token punctuation">.</span>count <span class="token operator"><</span> <span class="token number">6</span> <span class="token punctuation">{</span>
# <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">.</span>count<span class="token punctuation">)</span>
# <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
# <span class="token class-name">None</span>
# <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
# <span class="token punctuation">}</span>
#
<span class="token attribute attr-name">#[test]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">using_other_iterator_trait_methods</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> sum<span class="token punctuation">:</span> <span class="token keyword">u32</span> <span class="token operator">=</span> <span class="token class-name">Counter</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">zip</span><span class="token punctuation">(</span><span class="token class-name">Counter</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">skip</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token closure-punctuation punctuation">|</span></span> a <span class="token operator">*</span> b<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>x<span class="token closure-punctuation punctuation">|</span></span> x <span class="token operator">%</span> <span class="token number">3</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token macro property">assert_eq!</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> sum<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><span class="caption">示例 13-23:使用自定义的 <code>Counter</code> 迭代器的多种方法</span></p> <p>注意 <code>zip</code> 只产生四对值;理论上第五对值 <code>(5, None)</code> 从未被产生,因为 <code>zip</code> 在任一输入迭代器返回 <code>None</code> 时也返回 <code>None</code>。</p> <p>所有这些方法调用都是可能的,因为我们指定了 <code>next</code> 方法如何工作,而标准库则提供了其它调用 <code>next</code> 的方法的默认实现。</p></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-c6073ba8 data-v-c6073ba8><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-c6073ba8><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-c6073ba8></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-c6073ba8></path></svg></div></div></div>
<script src="/assets/js/app.e6b14c5e.js" defer></script><script src="/assets/js/3.ecc21787.js" defer></script><script src="/assets/js/1.032ec45e.js" defer></script><script src="/assets/js/76.ad390b83.js" defer></script>
</body>
</html>