Rust 如何处理懒惰的迭代器?

Rust 如何处理懒惰的迭代器?,rust,iterator,lazy-evaluation,Rust,Iterator,Lazy Evaluation,我正在尝试通过迭代器使用map()对数组进行排序 struct A { b: Vec<B>, } #[derive(PartialEq, Eq, PartialOrd, Ord)] struct B { c: Vec<i32>, } fn main() { let mut a = A { b: Vec::new() }; let b = B { c: vec![5, 2, 3] }; a.b.push(b); a.b

我正在尝试通过迭代器使用
map()
对数组进行排序

struct A {
    b: Vec<B>,
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct B {
    c: Vec<i32>,
}

fn main() {
    let mut a = A { b: Vec::new() };

    let b = B { c: vec![5, 2, 3] };
    a.b.push(b);

    a.b.iter_mut().map(|b| b.c.sort());
}
这是真的,
sort()
实际上并没有在这里调用。中描述了此警告,但我不明白为什么使用
iter_mut()
的这种变体可以正常工作:

a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
我不明白为什么使用
iter_mut()
的这种变化效果很好:

a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
它之所以有效,是因为
find
并不懒惰;它是迭代器消费者。它返回一个
选项
而不是
迭代器
。这可能就是它让您感到困惑的原因,因为
选项
还有一个
映射
方法,这就是您在这里使用的方法


正如其他人所说,
map
旨在转换数据,而不会修改数据,也不会产生任何其他副作用。如果确实要使用
映射
,可以映射集合并将其分配回:

fn main() {
    let mut a = A { b: Vec::new() };
    let mut b = B { c: vec![5, 2, 3] };
    a.b.push(b);

    a.b =
        a.b.into_iter()
            .map(|mut b| {
                b.c.sort();
                b
            })
            .collect();
}

请注意,vector的
sort
方法返回
()
,因此您必须从映射函数显式返回已排序的向量。

正如您链接到的书所述:

如果您试图对迭代器执行闭包以消除其副作用,请改用
for

这样它就可以工作了,而且对任何阅读代码的人来说都更加清晰。当你想将一个向量转换成另一个向量时,你应该使用
map

我使用。 根据该文件:

这相当于在迭代器上为循环使用
,尽管在闭包中不可能使用
中断
继续
。通常使用
for
循环更为惯用,但是
for_每个
在处理较长迭代器链末尾的项目时可能更清晰。在某些情况下,
for_each
也可能比循环快,因为它将在
Chain
之类的适配器上使用内部迭代


我真的不确定你想要实现什么。不清楚
obj
变量的类型是什么。请提供显示错误的完整MCVE。旁注:您可能应该只为o-in&mut-obj.numbers{}
做一个
,然后在循环中做您的工作对不起,我查看了OP,发现我简化到了毫无意义的地步。更新中有正确的版本。您说“工作正常”,但它获取迭代器的第一个元素并对其排序。这是期望的结果吗
.next()
是一种更清晰的方法来生成第一个元素,而不是使用
.find()
。不,我错过了这一部分,这不是预期的行为。因此,对于a.b.iter_mut(){b.c.sort();}
是Rust中的惯用方法吗?我的印象是,只要有可能,就应该使用迭代器而不是for循环。当您有一个向量并且希望其内容采用不同的格式而不修改原始向量时,就可以使用Map。如果要以破坏性方式修改向量,应该使用循环。@andreyg,是的,这将是惯用的方法,不,迭代器不应该总是用来代替for循环-这实际上是不可能的,因为迭代器是惰性的,而for循环不是。您应该在适当的时候使用迭代器转换器,但是如果您需要以一些非标准的方式处理结果(例如,当诸如
fold()
find()
或其他“终端”操作不合适时),您必须使用
for
循环。for循环是一种仅用于迭代器的语言功能。