我有一些实现std::iter::Iterator
的东西,我想知道是否有> 0
个元素。这样做的标准方法是什么? count() > 0
看起来太贵了。
我看到两位候选人:any(|_| true)
和nth(0).is_some()
,但我应该选择哪一位,以便将来的读者可以了解我在这里查看的内容?
答案 0 :(得分:9)
我会写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
}
在很多情况下,我会使用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
}
所以未来的读者可以在视线中理解
我add a method on iterator命名为is_empty
。
答案 1 :(得分:5)
为is_empty
实施Iterator
的规范方法不是这样做。 Iterator
是this,因此根据定义,如果没有迭代,就无法知道它是否还有其他元素。
从逻辑上讲,迭代器似乎应该很容易知道它是否还有更多的元素,但如果它的大小已知,则只能是这种情况(没有迭代)。事实上,lazy实现了is_empty
。
要检查Iterator
是否为空,您必须尝试迭代并检查是否收到None
,但是(如@Shepmaster所述),您只能在不推进{{Iterator
的情况下执行此操作1}}当你有Peekable
Iterator
时。您可以在下一个元素peek()
查看是否is_none()
:
let mut iterator = vec![1,2,3].into_iter().peekable();
println!("is_empty: {}", iterator.peek().is_none());
在考虑实施Iterator
时,这变得更加明显,只需要提供next
函数,该函数返回Some
或None
以指示是否还有其他元素存在。我们可以提供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}
}
}
因此,创建Peekable
迭代器并调用.peek().is_none()
实际上非常明确,未来的读者应该很容易理解。如果您只处理已知大小的迭代器,那么您可以将类型进一步限制为ExactSizeIterator
并使用is_empty
。如果您要为普通is_empty
添加Iterator
,则只会隐藏必须调用其next
函数以确定它是否为空的事实。