目录
最后更新时间2024-05-24
rust中迭代器的使用(iter().map()与for循环的区别)
map()与for的描述
rust源码中关于iter().map()函数的解释:
rust
// core::iter::traits::iterator::Iterator
/// Takes a closure and creates an iterator which calls that closure on each
/// element.
///
/// `map()` transforms one iterator into another, by means of its argument:
/// something that implements [`FnMut`]. It produces a new iterator which
/// calls this closure on each element of the original iterator.
///
/// If you are good at thinking in types, you can think of `map()` like this:
/// If you have an iterator that gives you elements of some type `A`, and
/// you want an iterator of some other type `B`, you can use `map()`,
/// passing a closure that takes an `A` and returns a `B`.
///
/// `map()` is conceptually similar to a [`for`] loop. However, as `map()` is
/// lazy, it is best used when you're already working with other iterators.
/// If you're doing some sort of looping for a side effect, it's considered
/// more idiomatic to use [`for`] than `map()`.
///
/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// 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);
/// ```
///
/// If you're doing some sort of side effect, prefer [`for`] to `map()`:
///
/// ```
/// # #![allow(unused_must_use)]
/// // don't do this:
/// (0..5).map(|x| println!("{x}"));
///
/// // it won't even execute, as it is lazy. Rust will warn you about this.
///
/// // Instead, use for:
/// for x in 0..5 {
/// println!("{x}");
/// }
/// ```
fn map<B, F>(self, f: F) -> Map<Self, F>
where
Self: Sized,
F: FnMut(Self::Item) -> B,
{
Map::new(self, f)
}
上述官方解释比较难以理解,这里解释一下官方的解释:
iter().map()
和for
循环都是用来遍历集合(如Vec
、数组或其他迭代器)的常用方法,但它们在使用场景、目的和返回值方面有所不同。
- iter().map()
iter().map()
是Rust标准库提供的迭代器适配器方法之一,用于对集合中的每个元素应用一个函数,生成一个新的迭代器,该迭代器产生的是原函数应用结果的序列。它主要用于数据转换,且不会修改原集合。map操作是惰性的,即直到你通过collect()
、for_each()
等方法消费这个新迭代器时,转换操作才真正执行。
示例:
rust
let numbers = vec![1, 2, 3, 4];
let doubled: Vec<i32> = numbers.iter().map(|&x| x * 2).collect();
// doubled 现在是 vec![2, 4, 6, 8]
- for循环
for
循环则是一种更通用的迭代结构,它可以遍历任何实现了IntoIterator
特质的集合。for
循环允许你对集合中的每个元素执行一系列操作,这些操作可以是任意的,包括打印、修改集合内容、计算某个值或调用函数等。与map()
不同,for
循环通常用于有副作用的操作,或者当不需要保留转换结果时。
示例:
rust
let mut numbers = vec![1, 2, 3, 4];
for num in &mut numbers {
*num *= 2;
}
// numbers 现在是 vec![2, 4, 6, 8]
区别
目的: iter().map()主要用于无副作用的数据转换,并生成新的数据序列;而for循环适用于任何需要遍历并可能带有副作用操作的场景。
返回值: map返回一个新的迭代器,其中包含转换后的值;for循环没有直接返回值,主要用于执行过程中的操作。
惰性与立即执行: map是惰性的,需要进一步的动作(如collect)来实际执行转换;for循环则是立即执行的。
修改原集合: map不修改原集合,而for循环可以通过可变引用修改集合内容。
选择哪种方式取决于你的具体需求:是否需要保留原集合、是否需要进行数据转换、以及是否执行有副作用的操作。
总结
iter().map()
主要用于将数据集中的每个元素转换为另一个形式,创建出一个新的数据集(不改变原数据),适用于无副作用的数据转换场景。比如,将一个整数集合转换为对应的字符串集合,或对每个元素应用某种计算规则得到新的值并创建新的集合。
for
循环则更加灵活,既可以用作简单的遍历查看元素,也可以用来直接修改原数据集中的元素。当你需要对集合中的每个元素执行可能包含副作用的操作(如修改元素、打印输出 、基于当前元素影响外部状态等)时,for
循环是更合适的选择。