Skip to content

Commit 3b1bad1

Browse files
committed
Add Iterator::at_least() and Iterator::at_most() API
1 parent 0248c6f commit 3b1bad1

File tree

2 files changed

+3753
-0
lines changed

2 files changed

+3753
-0
lines changed

library/core/src/iter/traits/iterator.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,144 @@ pub trait Iterator {
22662266
self.try_fold((), check(f)) == ControlFlow::BREAK
22672267
}
22682268

2269+
/// Tests if at least `n` elements of the iterator matches a predicate.
2270+
///
2271+
/// `at_least()` takes a usize `n` and a closure that returns `true` or `false`. It applies
2272+
/// this closure to each element of the iterator, and if more than `n` of them return
2273+
/// `true`, then so does `at_least()`. If less than `n` of them return `true`, it
2274+
/// returns `false`.
2275+
///
2276+
/// `at_least()` is short-circuiting; in other words, it will stop processing
2277+
/// as soon as it finds `n` `true`, given that no matter what else happens,
2278+
/// the result will also be `true`.
2279+
///
2280+
/// An empty iterator returns `false`.
2281+
///
2282+
/// # Examples
2283+
///
2284+
/// Basic usage:
2285+
///
2286+
/// ```
2287+
/// let a = [1, 2, 3];
2288+
///
2289+
/// assert!(a.iter().at_least(1, |&x| x > 0));
2290+
///
2291+
/// assert!(!a.iter().at_least(1, |&x| x > 5));
2292+
/// ```
2293+
///
2294+
/// Stopping at the `n`th `true`:
2295+
///
2296+
/// ```
2297+
/// let a = vec![1, 2, 3, 4, 5];
2298+
///
2299+
/// let mut iter = a.iter();
2300+
///
2301+
/// assert!(iter.at_least(0, |&x| x % 2 == 0));
2302+
/// assert!(iter.at_least(1, |&x| x % 2 == 0));
2303+
/// assert!(iter.at_least(2, |&x| x % 2 == 0));
2304+
/// assert!(!iter.at_least(3, |&x| x % 2 == 0));
2305+
///
2306+
/// // we can still use `iter`, as there are more elements.
2307+
/// let a = [1, 2, 3];
2308+
/// let mut iter = a.iter();
2309+
/// assert!(iter.at_least(1, |&x| x > 0));
2310+
/// assert_eq!(iter.next(), Some(&2));
2311+
/// ```
2312+
#[inline]
2313+
#[unstable(feature = "at_least", reason = "new API", issue = "none")]
2314+
fn at_least<F>(&mut self, n: usize, f: F) -> bool
2315+
where
2316+
Self: Sized,
2317+
F: FnMut(Self::Item) -> bool,
2318+
{
2319+
#[inline]
2320+
fn check<T>(
2321+
n: usize,
2322+
mut f: impl FnMut(T) -> bool,
2323+
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
2324+
move |mut i, x| {
2325+
i += f(x) as usize;
2326+
2327+
if i < n {
2328+
ControlFlow::Continue(i)
2329+
} else {
2330+
ControlFlow::Break(i)
2331+
}
2332+
}
2333+
}
2334+
2335+
matches!(self.try_fold(0, check(n, f)), ControlFlow::Break(_))
2336+
}
2337+
2338+
/// Tests if at most `n` elements of the iterator matches a predicate.
2339+
///
2340+
/// `at_most()` takes a usize `n` and a closure that returns `true` or `false`. It applies
2341+
/// this closure to each element of the iterator, and if less than `n` of them return
2342+
/// `true`, then so does `at_least()`. If more than `n` of them return `true`, it
2343+
/// returns `false`.
2344+
///
2345+
/// `at_most()` is short-circuiting; in other words, it will stop processing
2346+
/// as soon as it finds `n` `false`, given that no matter what else happens,
2347+
/// the result will also be `false`.
2348+
///
2349+
/// An empty iterator returns `true`.
2350+
///
2351+
/// # Examples
2352+
///
2353+
/// Basic usage:
2354+
///
2355+
/// ```
2356+
/// let a = [1, 2, 3];
2357+
///
2358+
/// assert!(a.iter().at_most(1, |&x| x > 3));
2359+
///
2360+
/// assert!(!a.iter().at_most(1, |&x| x > 0));
2361+
/// ```
2362+
///
2363+
/// Stopping at the `n + 1`th `true`:
2364+
///
2365+
/// ```
2366+
/// let a = vec![1, 2, 3, 4, 5];
2367+
///
2368+
/// let mut iter = a.iter();
2369+
///
2370+
/// assert!(iter.at_least(0, |&x| x % 2 == 0));
2371+
/// assert!(iter.at_least(1, |&x| x % 2 == 0));
2372+
/// assert!(iter.at_least(2, |&x| x % 2 == 0));
2373+
/// assert!(!iter.at_least(3, |&x| x % 2 == 0));
2374+
///
2375+
/// // we can still use `iter`, as there are more elements.
2376+
/// let a = [1, 1, 3];
2377+
/// let mut iter = a.iter();
2378+
/// assert!(!iter.at_most(1, |&x| x == 1));
2379+
/// assert_eq!(iter.next(), Some(&3));
2380+
/// ```
2381+
#[inline]
2382+
#[unstable(feature = "at_most", reason = "new API", issue = "none")]
2383+
fn at_most<F>(&mut self, n: usize, f: F) -> bool
2384+
where
2385+
Self: Sized,
2386+
F: FnMut(Self::Item) -> bool,
2387+
{
2388+
#[inline]
2389+
fn check<T>(
2390+
n: usize,
2391+
mut f: impl FnMut(T) -> bool,
2392+
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
2393+
move |mut i, x| {
2394+
i += f(x) as usize;
2395+
2396+
if i <= n {
2397+
ControlFlow::Continue(i)
2398+
} else {
2399+
ControlFlow::Break(i)
2400+
}
2401+
}
2402+
}
2403+
2404+
matches!(self.try_fold(0, check(n, f)), ControlFlow::Continue(_))
2405+
}
2406+
22692407
/// Searches for an element of an iterator that satisfies a predicate.
22702408
///
22712409
/// `find()` takes a closure that returns `true` or `false`. It applies

0 commit comments

Comments
 (0)