为迭代器实现is_empty的规范方法是什么?

use*_*932 9 rust

我有一些实现的东西,std::iter::Iterator我想知道是否有> 0元素.这样做的标准方法是什么?count() > 0看起来太贵了.

我看到两个候选人:any(|_| true)而且nth(0).is_some(),但是我应该选择哪一个,以便未来的读者能够理解我在这里检查的内容?

She*_*ter 11

我会写的iter.next().is_some().

但是,您需要注意这样做会推进迭代器.

fn main() {
    let scores = [1, 2, 3];
    let mut iter = scores.iter();

    println!("{}", iter.next().is_some()); // true
    println!("{}", iter.next().is_some()); // true
    println!("{}", iter.next().is_some()); // true
    println!("{}", iter.next().is_some()); // false
}
Run Code Online (Sandbox Code Playgroud)

在很多情况下我会使用Peekable:

fn main() {
    let scores = [1, 2, 3];
    let mut iter = scores.iter().peekable();

    println!("{}", iter.peek().is_some()); // true
    println!("{}", iter.peek().is_some()); // true
    println!("{}", iter.peek().is_some()); // true
    println!("{}", iter.peek().is_some()); // true
}
Run Code Online (Sandbox Code Playgroud)

所以未来的读者可以在视线中理解

将在迭代器上添加一个名为的方法is_empty.


小智 5

实行规范的方法is_emptyIterator不这样做.一个Iterator懒惰的,所以根据定义,不知道它是否还有迭代的元素.

从逻辑上讲,迭代器似乎应该很容易知道它是否还有更多的元素,但如果它的大小已知,则只能是这种情况(没有迭代).事实上,ExactSizeIterator实现了is_empty.

要检查是否Iterator是空的,你必须尝试迭代,并查看是否收到了None,但是(如@Shepmaster提到的),你只能这样做没有推进Iterator,当你有一个Peekable Iterator.你可以peek()在下一个元素并检查它是否is_none():

let mut iterator = vec![1,2,3].into_iter().peekable();
println!("is_empty: {}", iterator.peek().is_none());
Run Code Online (Sandbox Code Playgroud)

考虑到在实施时,这一点更为明显Iterator,一个只需要提供一个next返回两个函数SomeNone指示进一步元素是否存在.我们可以提供一个next随机决定下一个元素是否存在的实现,这清楚地表明我们无法知道next我们的迭代器是否为空:

struct RandomThings {}
impl Iterator for RandomThings {
    type Item = bool;
    fn next(&mut self) -> Option<bool> {
        let has_next = rand::random::<bool>();
        if has_next {Some(true)} else {None}
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,创建PeekableIterator和调用.peek().is_none()实际上是非常明确的,未来的读者应该很容易理解.如果您只处理已知大小的迭代器,那么您可以进一步限制类型ExactSizeIterator并使用is_empty.如果你要is_empty为普通人添加,Iterator你只会隐藏这样一个事实,即next必须调用它的函数来确定它是否为空.