diff --git a/corelib/src/iter/adapters.cairo b/corelib/src/iter/adapters.cairo
index e938418f280..5a1a3853773 100644
--- a/corelib/src/iter/adapters.cairo
+++ b/corelib/src/iter/adapters.cairo
@@ -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;
diff --git a/corelib/src/iter/adapters/filter.cairo b/corelib/src/iter/adapters/filter.cairo
new file mode 100644
index 00000000000..896fad3c8fd
--- /dev/null
+++ b/corelib/src/iter/adapters/filter.cairo
@@ -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 {
+ pub iter: I,
+ pub predicate: P,
+}
+
+pub fn filter_iterator(iter: I, predicate: P) -> Filter {
+ Filter { iter, predicate }
+}
+
+impl FilterIterator<
+ I,
+ P,
+ impl TIter: Iterator,
+ +core::ops::Fn
[Output: bool],
+ +Destruct,
+ +Destruct
,
+ +Destruct,
+> of Iterator> {
+ type Item = TIter::Item;
+ fn next(ref self: Filter) -> Option {
+ self.iter.find(@self.predicate)
+ }
+}
diff --git a/corelib/src/iter/traits/iterator.cairo b/corelib/src/iter/traits/iterator.cairo
index 0bd351f48b0..308432c787f 100644
--- a/corelib/src/iter/traits/iterator.cairo
+++ b/corelib/src/iter/traits/iterator.cairo
@@ -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};
@@ -364,6 +364,8 @@ pub trait Iterator {
/// // 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[Output: bool],
@@ -385,6 +387,41 @@ pub trait Iterator {
}
}
+ /// 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[Output: bool],
+ +Destruct
,
+ +Destruct,
+ +Destruct,
+ >(
+ self: T, predicate: P,
+ ) -> Filter {
+ 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
diff --git a/corelib/src/test/iter_test.cairo b/corelib/src/test/iter_test.cairo
index 2a176836b0a..d3189a51d0e 100644
--- a/corelib/src/test/iter_test.cairo
+++ b/corelib/src/test/iter_test.cairo
@@ -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);
+}