Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I find out if a filtered iterator is empty? [duplicate]

Tags:

rust

I have a filtered iterator like so:

let filt_it = a_vector.iter().filter(|x| condition_on_x);

Is there a way I can find out whether it's empty?

I need the iterator to stay an iterator for later use and it doesn't seem possible to clone filtered iterators.

like image 699
SquattingSlavInTracksuit Avatar asked Feb 13 '18 23:02

SquattingSlavInTracksuit


People also ask

How do I check if an iterator is empty in Python?

# Create a list of objects but runs out the iterator. l = [_ for _ in iterator] # If the list is not empty then the iterator had elements; else it was empty. if l : pass # Use the elements of the list (i.e. from the iterator) else : pass # Iterator was empty, thus list is empty.

Can iterators be reused?

iterators are not reusable; you need to get a fresh Iterator from the Iterable collection each time you want to iterate over the elements.

What is true about iterators scala?

An iterator is not a collection, but rather a way to access the elements of a collection one by one. The two basic operations on an iterator it are next and hasNext. A call to it. next() will return the next element of the iterator and advance the state of the iterator.

How to define iterator in scala?

It provide us hasNext() and next() method to work with collection elements. The basic syntax to define the iterate in scala is as follows; valiterate_name = Iterator(value1, value2, value3, so on ....) In this way, we can define an iterate in scala.


1 Answers

You can make your iterator peekable and peek the first item; if it's None, then the iterator is empty. peek doesn't consume the item1, so the next call to next will return it. However, peekable consumes the iterator, so you'll have to pass the Peekable around — but Peekable is also an Iterator, so if your code expects an Iterator or an IntoIterator, it'll work fine.

let filt_it = a_vector.iter().filter(|x| condition_on_x).peekable();
if filt_it.peek().is_some() {
    // The iterator is not empty, process it.
    process(filt_it);
}

Another option is to clone the iterator, call next once on the cloned iterator; again, if the result is None, then the iterator is empty. Then, you can process the original iterator, which will yield the first item again.

This option might not always work; not all iterators can be cloned. However, Filter implements Clone when both the iterator and the predicate function are Clone. Starting with Rust 1.26.0, closures implement Clone when possible (before 1.26.0, closures would never implement Clone).

Also, this option is probably not viable if the iterator has a side effect, since the side effect may occur twice, or if the iterator is not deterministic, as both copies of the iterator may yield different results.


1 If you call peekable with a mutable reference to your iterator, you can actually keep the original iterator around after dropping the Peekable. However, if you had called peek before dropping the Peekable, you'll see that it actually consumed the first item in the original iterator. That's completely normal; Iterator itself doesn't provide an interface for peeking. Peekable will store the peeked-at item so it can return it in the following call to next, but if you drop the Peekable, then that stored item will also be dropped.

like image 135
Francis Gagné Avatar answered Sep 21 '22 01:09

Francis Gagné