# 翻译来源

https://github.com/rustomax/rust-iterators

API

# 如何编译运行例子

git clone https://github.com/rustomax/rust-iterators.git
cd rust-iterators/
cargo run

# 0介绍

(enumerate)、反复申明(iterate)这些事物。在编程中，有多种方式产生重复事物(repetition)，其中最为人熟知的是C风格的for循环。

for ( x = 0; x < 10; ++x ) {
// do something
}

# 1.基本Range

for i in 1..11 {
print!("{} ", i);
}
// output: 1 2 3 4 5 6 7 8 9 10

#![feature(inclusive_range_syntax)]

for i in 1...10 {
print!("{} ", i);
}
// output: 1 2 3 4 5 6 7 8 9 10

let mut n: i32 = 0;
for _ in 0..10 {
n += 1;
}
println!("num = {}", n);
// output: num = 10

println!("num = {}", (0..10).count());
// output: num = 10

# 2.深层发掘（Digging Deeper）

for i in (0..21).filter(|x| (x % 2 == 0)) {
print!("{} ", i);
}
// output: 0 2 4 6 8 10 12 14 16 18 20

for i in (0..21).filter(|x| (x % 2 == 0) && (x % 3 == 0)) {
print!("{} ", i);
}
// output: 0 6 12 18

for i in (0..11).rev() {
print!("{} ", i);
}
// output: 10 9 8 7 6 5 4 3 2 1 0

for i in (1..11).map(|x| x * x) {
print!("{} ", i);
}
// output: 1 4 9 16 25 36 49 64 81 100

fold()是一个非常强大的方法。 它返回一个特殊的“累加器”类型闭包的结果给迭代器的所有元素，得到一个单一的值。 下面的迭代器产生从1到5的数字的平方和。

#![feature(inclusive_range_syntax)]

let result = (1...5).fold(0, |acc, x| acc + x * x);
println!("result = {}", result);

// output: result = 55

#![feature(inclusive_range_syntax)]

let mut acc = 0;

for x in 1...5 {
acc += x * x;
}

let result = acc;
println!("result = {}", result);

// output: result = 55

# 3.数组迭代（Iterating over Arrays）

let cities = ["Toronto", "New York", "Melbourne"];

for city in cities.iter() {
print!("{}, ", city);
}
// output: Toronto, New York, Melbourne,

#![feature(inclusive_range_syntax)]

for i in (0...10).rev().filter(|x| (x % 2 == 0)) {
print!("{} ", i);
}
// output: 10 8 6 4 2 0

let c = (1..4).chain(6..9);

for i in c {
print!("{} ", i);
}
// output: 1 2 3 6 7 8

let r = (1..20)
.filter(|&x| x % 5 == 0)
.chain((6..9).rev());

for i in r {
print!("{} ", i);
}
// output: 5 10 15 8 7 6

let cities = ["Toronto", "New York", "Melbourne"];
let populations = [2_615_060, 8_550_405, ‎4_529_500];

let matrix = cities.iter().zip(populations.iter());

for (c, p) in matrix {
println!("{:10}: population = {}", c, p);
}
// output:
// Toronto   : population = 2615060
// New York  : population = 8550405
// Melbourne : population = 4529500

# 5.字符Range（Ranges of Characters）

[dependencies]
char-iter = "0.1"

extern crate char_iter;

for c in char_iter::new('Д', 'П') {
print!("{} ", c);
}
// output: Д Е Ж З И Й К Л М Н О П

# 6.向量迭代（Iterating over Vectors）

let nums = vec![1, 2, 3, 4, 5];

for i in nums.iter() {
print!("{} ", i);
}
// output: 1 2 3 4 5

let nums = vec![1, 2, 3, 4, 5];
for i in &nums {
print!("{} ", i);
}
// output: 1 2 3 4 5

let mut nums = vec![1, 2, 3, 4, 5];
for i in &mut nums {
*i *= 2;
}
println!("{:?}", nums);

//output: [2, 4, 6, 8, 10]

let nums = vec![1, 2, 3, 4, 5];
let nums = nums.iter().map(|x| x * 2);
println!("{:?}", nums);

//output: [2, 4, 6, 8, 10]

let mut nums = vec![1, 2, 3, 4, 5];
for i in &mut nums {
nums.push(*i);
}
println!("{:?}", nums);

let v = (1..11).collect::<Vec<i32>>();
println!("{:?}", v);
// output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let v = vec![1, 2, 3];
for (i, n) in v.iter().enumerate() {
println!("v[{}] = {}", i, n);
}
// output:
// v[0] = 1
// v[1] = 2
// v[2] = 3

min()max()，例如返回Option，分别包含向量元素的最小值和最大值：

let v = vec![3, 5, 0, -2, 3, 4, 1];
let max = v.iter().max();
let min = v.iter().min();

println!("max = {:?}, min = {:?}", max, min);

// output: max = Some(5), min = Some(-2)

sum()返回迭代器中所有值的总和。 以下程序利用sum()方法来计算一个相当平庸的学生的平均成绩：

let grades = vec![4, 5, 6, 9, 7, 4, 8];
let gpa = sum as f32 / grades.len() as f32;

println!("sum = {}, gpa = {:.2}", sum, gpa);

// output: sum = 43, gpa = 6.14

# 7.无限与超越(Infinity and Beyond)

let r = (1..).collect::<Vec<i32>>();

(1..)定义了一个从1开始并且无限增量的Range。 实际上，这样的程序编译和运行，但最终崩溃的错误消息：fatal runtime error: out of memory。 那么，你可能会说这不是很实际。 事实上，无限范围本身是无用的。 让他们有用的是将他们与其他适配器和消费者结合起来。

let v = (1..)
.map(|x| x * x)
.filter(|x| x % 5 == 0 )
.take(10)
.collect::<Vec<i32>>();

println!("{:?} ", v);

// output: [25, 100, 225, 400, 625, 900, 1225, 1600, 2025, 2500]

# 8.Itertools

itertools包含强大的附加迭代器适配器。 以下是一些例子。

[dependencies]
itertools = "0.6"

extern crate itertools;
use itertools::Itertools;

for i in (0..11).step(2) {
print!("{} ", i);
}

//output: 0 2 4 6 8 10

unique()适配器消除了迭代器的重复。 重复项不需要顺序。

extern crate itertools;
use itertools::Itertools;

let data = vec![1, 4, 3, 1, 4, 2, 5];
let unique = data.iter().unique();

for d in unique {
print!("{} ", d);
}

//output: 1 4 3 2 5

join()适配器将迭代器元素组合为单个字符串，元素之间有一个分隔符。

extern crate itertools;
use itertools::Itertools;

let creatures = vec!["banshee", "basilisk", "centaur"];
let list = creatures.iter().join(", ");
println!("In the enchanted forest, we found {}.", list);

// output: In the enchanted forest, we found banshee, basilisk, centaur.

sorted_by()适配器将自定义排序顺序应用于迭代器元素，返回排序后的向量。 根据2016年“世界幸福指数”，以下计划将打印出前5名最幸福的国家。

sorted_by() 使用Ordering trait排序

extern crate itertools;
use itertools::Itertools;

let happiness_index = vec![ ("Austria", 12), ("Costa Rica", 14), ("Norway", 4),
("Australia", 9), ("Netherlands", 7), ("New Zealand", 8), ("United States", 13),
("Israel", 11), ("Denmark", 1), ("Finland", 5), ("Iceland", 3),
("Sweden", 10), ("Canada", 6), ("Puerto Rico", 15), ("Switzerland", 2) ];

let top_contries = happiness_index
.into_iter()
.sorted_by(|a, b| (&a.1).cmp(&b.1))
.into_iter()
.take(5);

for (country, rating) in top_contries {
println!("# {}: {}", rating, country);
}

// output:
// # 1: Denmark
// # 2: Switzerland
// # 3: Iceland
// # 4: Norway
// # 5: Finland

Rust的优点在于，你可以使用通用语言工具来扩展它。 让我们利用这个强大的力量，创造我们自己的迭代器！ 我们将构建一个非常简单的迭代器，产生一系列由浮点数(f32，f32)组成的温度(华氏，摄氏)对。 温度使用公知的公式计算：°C =(°F-32)/ 1.8

struct FahrToCelc {
fahr: f32,
step: f32,
}

impl FahrToCelc {
fn new(fahr: f32, step: f32) -> FahrToCelc {
FahrToCelc { fahr: fahr, step: step }
}
}

• 定义Item类型。 它描述了迭代器将产生什么样的东西。 如前所述，我们的迭代器产生由浮点数(f32，f32)元组表示的温度对(华氏，摄氏)，所以我们的Item类型定义如下所示：
 type Item = (f32, f32);
• 函数next()实际上会生成下一个Itemnext()self进行可变引用( mutable reference)，并返回一个封装下一个值的Option。 我们必须返回一个选项而不是项目本身的原因是因为许多迭代器需要考虑它们已经达到序列结束的情况，在这种情况下它们返回None。 由于我们的迭代器生成一个无限序列，我们的next()方法将始终返回Option <Self :: Item>。 因此，我们的next()函数声明如下所示：
fn next (&mut self) -> Option<Self::Item>

next()函数通常也会进行一些内部管理。 我们逐步增加华氏温度fahr，以便在随后的迭代中返回。 对内部字段进行这些修改是我们需要将self的可变引用传递给next()作为参数的原因。

impl Iterator for FahrToCelc {
type Item = (f32, f32);

fn next (&mut self) -> Option<Self::Item> {
let curr_fahr = self.fahr;
let curr_celc = (self.fahr - 32.0) / 1.8;
self.fahr = self.fahr + self.step;
Some((curr_fahr, curr_celc))
}
}

struct FahrToCelc {
fahr: f32,
step: f32,
}

impl FahrToCelc {
fn new(fahr: f32, step: f32) -> FahrToCelc {
FahrToCelc { fahr: fahr, step: step }
}
}

impl Iterator for FahrToCelc {
type Item = (f32, f32);

fn next (&mut self) -> Option<Self::Item> {
let curr_fahr = self.fahr;
let curr_celc = (self.fahr - 32.0) / 1.8;
self.fahr = self.fahr + self.step;
Some((curr_fahr, curr_celc))
}
}

fn main() {
// pass the starting temperature and step to the initializer function
let ftc = FahrToCelc::new(0.0, 5.0);

// produce the iterator table of first 5 values
let temp_table = ftc.take(5);

// print out the temperature table nicely
for (f, c) in temp_table {
println!("{:7.2} °F = {:7.2} °C", f, c);
}
}

// output:
//  0.00 °F =  -17.78 °C
//  5.00 °F =  -15.00 °C
// 10.00 °F =  -12.22 °C
// 15.00 °F =   -9.44 °C
// 20.00 °F =   -6.67 °C

09-29 829

07-08 1万+
07-15 1784
10-21 3851
06-27 3338
09-10 1443
09-30 112
02-15 283
08-31 45
12-14 5982
02-22 883
12-19 40
01-09 127
12-06 7115
05-23 762