From 778ae4875cebc20906cbc1d4d4b61adc1f9c6fff Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Thu, 27 Feb 2025 13:40:55 +0200 Subject: [PATCH] Added `Iterator::any` and `Iterator::all`. commit-id:29be040b --- corelib/src/iter/traits/iterator.cairo | 70 ++++++++++++++++++++++++++ corelib/src/test/iter_test.cairo | 28 +++++++++++ 2 files changed, 98 insertions(+) diff --git a/corelib/src/iter/traits/iterator.cairo b/corelib/src/iter/traits/iterator.cairo index 39ea4a33312..97f96e909a4 100644 --- a/corelib/src/iter/traits/iterator.cairo +++ b/corelib/src/iter/traits/iterator.cairo @@ -382,6 +382,76 @@ pub trait Iterator { } } + /// 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[Output: bool], + +Destruct

, + +Destruct, + +Destruct, + >( + 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[Output: bool], + +Destruct

, + +Destruct, + +Destruct, + >( + 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 diff --git a/corelib/src/test/iter_test.cairo b/corelib/src/test/iter_test.cairo index e554cced46a..2e7a4dafa2f 100644 --- a/corelib/src/test/iter_test.cairo +++ b/corelib/src/test/iter_test.cairo @@ -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();