Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Iterator::any and Iterator::all. #7365

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions corelib/src/iter/traits/iterator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,76 @@ pub trait Iterator<T> {
}
}

/// Tests if any element of the iterator matches a predicate.
///
/// `any()` takes a closure that returns `true` or `false`. It applies this closure to each
/// element of the iterator, and if any of them return `true`, then so does `any()`. If they all
/// return `false`, it returns `false`.
///
/// `any()` is short-circuiting; in other words, it will stop processing as soon as it finds a
/// `true`, given that no matter what else happens, the result will also be `true`.
///
/// An empty iterator returns `false`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// assert!(array![1, 2, 3].into_iter().any(|x| x == 2));
///
/// assert!(!array![1, 2, 3].into_iter().any(|x| x > 5));
/// ```
fn any<
P,
+core::ops::Fn<P, (Self::Item,)>[Output: bool],
+Destruct<P>,
+Destruct<T>,
+Destruct<Self::Item>,
>(
ref self: T, predicate: P,
) -> bool {
match Self::next(ref self) {
None => false,
Some(x) => predicate(x) || Self::any(ref self, predicate),
}
}

/// Tests if every element of the iterator matches a predicate.
///
/// `all()` takes a closure that returns `true` or `false`. It applies this closure to each
/// element of the iterator, and if all of them return `true`, then so does `all()`. If any
/// of them return `false`, it returns `false`.
///
/// `all()` is short-circuiting; in other words, it will stop processing as soon as it finds a
/// `false`, given that no matter what else happens, the result will also be `false`.
///
/// An empty iterator returns `true`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// assert!(array![1, 2, 3].into_iter().all(|x| x > 0));
///
/// assert!(!array![1, 2, 3].into_iter().all(|x| x > 2));
/// ```
fn all<
P,
+core::ops::Fn<P, (Self::Item,)>[Output: bool],
+Destruct<P>,
+Destruct<T>,
+Destruct<Self::Item>,
>(
ref self: T, predicate: P,
) -> bool {
match Self::next(ref self) {
None => true,
Some(x) => predicate(x) && Self::all(ref self, predicate),
}
}

/// Searches for an element of an iterator that satisfies a predicate.
///
/// `find()` takes a closure that returns `true` or `false`. It applies
Expand Down
28 changes: 28 additions & 0 deletions corelib/src/test/iter_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,34 @@ fn test_iter_accum_product() {
assert_eq!((1_usize..=5).into_iter().product(), 120);
}

#[test]
fn test_iter_any() {
let mut iter = array![1, 2, 3].into_iter();
assert!(iter.any(|x| x == 2));
assert_eq!(iter.next(), Some(3));

let mut iter = array![1, 2, 3].into_iter();
assert!(!iter.any(|x| x == 5));
assert_eq!(iter.next(), None);

let mut iter = array![].into_iter();
assert!(!iter.any(|x| x == 1));
}

#[test]
fn test_iter_all() {
let mut iter = array![1, 1, 1].into_iter();
assert!(iter.all(|x| x == 1));
assert_eq!(iter.next(), None);

let mut iter = array![1, 2, 3].into_iter();
assert!(!iter.all(|x| x == 1));
assert_eq!(iter.next(), Some(3));

let mut iter = array![].into_iter();
assert!(iter.all(|x| x == 1));
}

#[test]
fn test_iter_find() {
let mut iter = array![1, 2, 3].into_iter();
Expand Down
Loading