为什么Iterator :: take_while取得迭代器的所有权?

Ale*_*mir 13 rust

我觉得很奇怪,Iterator::take_while它取得了迭代器的所有权.这似乎是一个有用的功能,能够获取满足某些功能但仍保留原始迭代器中其余元素的前x个元素.

我知道这与懒惰的实现不兼容take_while,但仍然感觉很有用.这只是被认为不足以包含在标准库中,还是还有其他一些我没有看到的问题?

She*_*ter 21

为了效率,所有迭代器适配器都按值获取原始迭代器.此外,获取原始迭代器的所有权可避免在不必要时处理生命周期.

如果您希望保留对原始迭代器的访问权限,则可以使用by_ref.这引入了一个间接层,但程序员选择在需要该功能时选择额外的工作:

fn main() {
    let v = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut i1 = v.iter();
    for z in i1.by_ref().take_while(|&&v| v < 4) {
    //         ^^^^^^^^^
        println!("Take While: {}", z);
    }

    for z in i1 {
        println!("Rest: {}", z);
    }
}
Run Code Online (Sandbox Code Playgroud)

有输出

Take While: 1
Take While: 2
Take While: 3
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Run Code Online (Sandbox Code Playgroud)

你注意到了4吗?那是因为一旦take_while选择一个值并决定不使用它,就没有地方可以"放回去".把它放回原点需要选择比一直需要更多的存储和缓慢.

我已经使用了itertools crate来处理这样的情况,特别是take_while_ref.


Kap*_*lan 5

如果事情变得太复杂,我们可能使用了错误的工具。
请注意,这里有 4。

fn main() {
    let v = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut i1 = v.iter().peekable();
    while let Some(z) = i1.next_if(|&n| n < &4) {
        println!("Take While: {z}");
    }
    for z in i1 {
        println!("Rest: {z}");
    }
}
Run Code Online (Sandbox Code Playgroud)
Take While: 1
Take While: 2
Take While: 3
Rest: 4
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Run Code Online (Sandbox Code Playgroud)

next_if 在迭代器的每个元素上调用

Playground
是的,OP 要求的take_whileShepmaster 的解决方案非常棒。