Skip to content

Commit

Permalink
feat(corelib): iter::adapters::Filter (#7152)
Browse files Browse the repository at this point in the history
  • Loading branch information
julio4 authored Jan 29, 2025
1 parent 601cf60 commit 6914ec6
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
5 changes: 5 additions & 0 deletions corelib/src/iter/adapters.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ mod peekable;
#[allow(unused_imports)]
pub(crate) use peekable::peekable_iterator;
pub use peekable::{Peekable, PeekableTrait};

mod filter;
pub use filter::Filter;
#[allow(unused_imports)]
pub(crate) use filter::filter_iterator;
31 changes: 31 additions & 0 deletions corelib/src/iter/adapters/filter.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// An iterator that filters the elements of `iter` with `predicate`.
///
/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`filter`]: Iterator::filter
#[must_use]
#[derive(Drop, Clone)]
pub struct Filter<I, P> {
pub iter: I,
pub predicate: P,
}

pub fn filter_iterator<I, P>(iter: I, predicate: P) -> Filter<I, P> {
Filter { iter, predicate }
}

impl FilterIterator<
I,
P,
impl TIter: Iterator<I>,
+core::ops::Fn<P, (@TIter::Item,)>[Output: bool],
+Destruct<I>,
+Destruct<P>,
+Destruct<TIter::Item>,
> of Iterator<Filter<I, P>> {
type Item = TIter::Item;
fn next(ref self: Filter<I, P>) -> Option<Self::Item> {
self.iter.find(@self.predicate)
}
}
41 changes: 39 additions & 2 deletions corelib/src/iter/traits/iterator.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::iter::adapters::{
Enumerate, Map, Peekable, Zip, enumerated_iterator, mapped_iterator, peekable_iterator,
zipped_iterator,
Enumerate, Filter, Map, Peekable, Zip, enumerated_iterator, filter_iterator, mapped_iterator,
peekable_iterator, zipped_iterator,
};
use crate::iter::traits::{Product, Sum};

Expand Down Expand Up @@ -364,6 +364,8 @@ pub trait Iterator<T> {
/// // we can still use `iter`, as there are more elements.
/// assert_eq!(iter.next(), Option::Some(3));
/// ```
///
/// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`.
fn find<
P,
+core::ops::Fn<P, (@Self::Item,)>[Output: bool],
Expand All @@ -385,6 +387,41 @@ pub trait Iterator<T> {
}
}

/// Creates an iterator which uses a closure to determine if an element
/// should be yielded. The closure takes each element as a snapshot.
///
/// Given an element the closure must return `true` or `false`. The returned
/// iterator will yield only the elements for which the closure returns
/// `true`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let a = array![0_u32, 1, 2];
///
/// let mut iter = a.into_iter().filter(|x| *x > 0);
///
/// assert_eq!(iter.next(), Option::Some(1));
/// assert_eq!(iter.next(), Option::Some(2));
/// assert_eq!(iter.next(), Option::None);
/// ```
///
/// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`.
#[inline]
fn filter<
P,
+core::ops::Fn<P, (@Self::Item,)>[Output: bool],
+Destruct<P>,
+Destruct<T>,
+Destruct<Self::Item>,
>(
self: T, predicate: P,
) -> Filter<T, P> {
filter_iterator(self, predicate)
}

/// 'Zips up' two iterators into a single iterator of pairs.
///
/// `zip()` returns a new iterator that will iterate over two other
Expand Down
8 changes: 8 additions & 0 deletions corelib/src/test/iter_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,11 @@ fn test_iter_find() {
assert_eq!(iter.find(|x| *x == 2), Option::Some(2));
assert_eq!(iter.next(), Option::Some(3));
}

#[test]
fn test_iter_adapter_filter() {
let mut iter = array![0_u32, 1, 2].into_iter().filter(|x| *x > 0);
assert_eq!(iter.next(), Option::Some(1));
assert_eq!(iter.next(), Option::Some(2));
assert_eq!(iter.next(), Option::None);
}

0 comments on commit 6914ec6

Please sign in to comment.