Skip to content

Commit e68680d

Browse files
committed
VecDeque: Add partition_point() #78021
1 parent bccbf9d commit e68680d

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

library/alloc/src/collections/vec_deque/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -2534,6 +2534,51 @@ impl<T> VecDeque<T> {
25342534
{
25352535
self.binary_search_by(|k| f(k).cmp(b))
25362536
}
2537+
2538+
/// Returns the index of the partition point according to the given predicate
2539+
/// (the index of the first element of the second partition).
2540+
///
2541+
/// The deque is assumed to be partitioned according to the given predicate.
2542+
/// This means that all elements for which the predicate returns true are at the start of the deque
2543+
/// and all elements for which the predicate returns false are at the end.
2544+
/// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
2545+
/// (all odd numbers are at the start, all even at the end).
2546+
///
2547+
/// If this deque is not partitioned, the returned result is unspecified and meaningless,
2548+
/// as this method performs a kind of binary search.
2549+
///
2550+
/// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`].
2551+
///
2552+
/// [`binary_search`]: slice::binary_search
2553+
/// [`binary_search_by`]: slice::binary_search_by
2554+
/// [`binary_search_by_key`]: slice::binary_search_by_key
2555+
///
2556+
/// # Examples
2557+
///
2558+
/// ```
2559+
/// #![feature(vecdeque_binary_search)]
2560+
/// use std::collections::VecDeque;
2561+
///
2562+
/// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into();
2563+
/// let i = deque.partition_point(|&x| x < 5);
2564+
///
2565+
/// assert_eq!(i, 4);
2566+
/// assert!(deque.iter().take(i).all(|&x| x < 5));
2567+
/// assert!(deque.iter().skip(i).all(|&x| !(x < 5)));
2568+
/// ```
2569+
#[unstable(feature = "vecdeque_binary_search", issue = "78021")]
2570+
pub fn partition_point<P>(&self, mut pred: P) -> usize
2571+
where
2572+
P: FnMut(&T) -> bool,
2573+
{
2574+
let (front, back) = self.as_slices();
2575+
2576+
if let Some(true) = back.first().map(|v| pred(v)) {
2577+
back.partition_point(pred) + front.len()
2578+
} else {
2579+
front.partition_point(pred)
2580+
}
2581+
}
25372582
}
25382583

25392584
impl<T: Clone> VecDeque<T> {

library/alloc/tests/vec_deque.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,24 @@ fn test_binary_search_by_key() {
16991699
assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3));
17001700
}
17011701

1702+
#[test]
1703+
fn test_partition_point() {
1704+
// Contiguous (front only) search:
1705+
let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into();
1706+
assert!(deque.as_slices().1.is_empty());
1707+
assert_eq!(deque.partition_point(|&v| v <= 3), 3);
1708+
1709+
// Split search (both front & back non-empty):
1710+
let mut deque: VecDeque<_> = vec![5, 6].into();
1711+
deque.push_front(3);
1712+
deque.push_front(2);
1713+
deque.push_front(1);
1714+
deque.push_back(10);
1715+
assert!(!deque.as_slices().0.is_empty());
1716+
assert!(!deque.as_slices().1.is_empty());
1717+
assert_eq!(deque.partition_point(|&v| v <= 5), 4);
1718+
}
1719+
17021720
#[test]
17031721
fn test_zero_sized_push() {
17041722
const N: usize = 8;

0 commit comments

Comments
 (0)