Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 35193cb

Browse files
committedJan 2, 2025
Add experimental Iterator::contains
1 parent eeeff9a commit 35193cb

File tree

5 files changed

+61
-0
lines changed

5 files changed

+61
-0
lines changed
 

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

+33
Original file line numberDiff line numberDiff line change
@@ -2770,6 +2770,39 @@ pub trait Iterator {
27702770
self.try_fold((), check(f)) == ControlFlow::Break(())
27712771
}
27722772

2773+
/// Returns `true` if the iterator contains a value.
2774+
///
2775+
/// `contains()` is short-circuiting; in other words, it will stop processing
2776+
/// as soon as the function finds the item in the `Iterator`.
2777+
///
2778+
/// This method checks the whole iterator, which is O(n). If the iterator is a sorted
2779+
/// slice, [`binary_search`](slice::binary_search) may be faster. If this is an iterator
2780+
/// on collections that have a `.contains()` or `.contains_key()` method (such as
2781+
/// `HashMap` or `BtreeSet`, using those methods directly will be faster.
2782+
///
2783+
/// # Examples
2784+
/// Basic usage:
2785+
/// ```
2786+
/// #![feature(iter_contains)]
2787+
/// assert_eq!(true, [1, 2, 3].iter().contains(2));
2788+
/// assert_eq!(false, [1, 2, 3].iter().contains(5));
2789+
/// ```
2790+
/// [`Iterator::contains`] can be used where [`slice::contains`] cannot be used:
2791+
/// ```
2792+
/// #![feature(iter_contains)]
2793+
/// let s = [String::from("a"), String::from("b"), String::from("c")];
2794+
/// assert_eq!(s.iter().contains("b"), s.iter().any(|e| e == "b"));
2795+
/// ```
2796+
#[inline]
2797+
#[unstable(feature = "iter_contains", reason = "new API", issue = "127494")]
2798+
fn contains<Q: ?Sized>(&mut self, item: Q) -> bool
2799+
where
2800+
Q: PartialEq<Self::Item>,
2801+
Self: Sized,
2802+
{
2803+
self.any(|elem| item == elem)
2804+
}
2805+
27732806
/// Searches for an element of an iterator that satisfies a predicate.
27742807
///
27752808
/// `find()` takes a closure that returns `true` or `false`. It applies

‎library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
#![feature(internal_impls_macro)]
119119
#![feature(ip)]
120120
#![feature(is_ascii_octdigit)]
121+
#![feature(iter_contains)]
121122
#![feature(lazy_get)]
122123
#![feature(link_cfg)]
123124
#![feature(non_null_from_ref)]

‎library/core/src/slice/iter/macros.rs

+10
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,16 @@ macro_rules! iterator {
289289
false
290290
}
291291

292+
fn contains<Q: ?Sized>(&mut self, item: Q) -> bool
293+
where
294+
Q: PartialEq<Self::Item>,
295+
Self: Sized,
296+
{
297+
// specialize
298+
self.any(|elem|item == elem)
299+
300+
}
301+
292302
// We override the default implementation, which uses `try_fold`,
293303
// because this simple implementation generates less LLVM IR and is
294304
// faster to compile.

‎library/core/src/str/iter.rs

+7
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,13 @@ impl Iterator for Bytes<'_> {
331331
self.0.any(f)
332332
}
333333

334+
fn contains<Q: ?Sized>(&mut self, item: Q) -> bool
335+
where
336+
Q: PartialEq<Self::Item>,
337+
{
338+
self.0.contains(item)
339+
}
340+
334341
#[inline]
335342
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
336343
where

‎library/core/tests/iter/traits/iterator.rs

+10
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ fn test_any() {
271271
assert!(!v.iter().any(|&x| x > 100));
272272
assert!(!v[..0].iter().any(|_| panic!()));
273273
}
274+
#[test]
275+
fn test_iterator_contains() {
276+
let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
277+
assert_eq!(true, v.iter().contains(3));
278+
assert_eq!(v.iter().contains(3), v.iter().any(|&x| x == 3));
279+
assert_eq!(false, v.iter().contains(10));
280+
assert_eq!(v.iter().contains(10), v.iter().any(|&x| x == 10));
281+
assert_eq!(true, Iterator::contains(&mut (1..=5), 3));
282+
assert_eq!(false, Iterator::contains(&mut (1..=5), 10));
283+
}
274284

275285
#[test]
276286
fn test_find() {

0 commit comments

Comments
 (0)
Failed to load comments.