Skip to content

Commit 0492f97

Browse files
committed
Return the true count from partition_in_place
1 parent cd0ebc4 commit 0492f97

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

src/libcore/iter/traits/iterator.rs

+35-6
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,7 @@ pub trait Iterator {
15131513

15141514
/// Reorder the elements of this iterator *in-place* according to the given predicate,
15151515
/// such that all those that return `true` precede all those that return `false`.
1516+
/// Returns the number of `true` elements found.
15161517
///
15171518
/// The relative order of partitioned items is not maintained.
15181519
///
@@ -1529,25 +1530,53 @@ pub trait Iterator {
15291530
/// let mut a = [1, 2, 3, 4, 5, 6, 7];
15301531
///
15311532
/// // Partition in-place between evens and odds
1532-
/// a.iter_mut().partition_in_place(|&n| n % 2 == 0);
1533+
/// let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0);
15331534
///
1534-
/// assert!(a[..3].iter().all(|&n| n % 2 == 0)); // evens
1535-
/// assert!(a[3..].iter().all(|&n| n % 2 == 1)); // odds
1535+
/// assert_eq!(i, 3);
1536+
/// assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens
1537+
/// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
15361538
/// ```
15371539
#[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "0")]
1538-
fn partition_in_place<'a, T: 'a, P>(mut self, mut predicate: P)
1540+
fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
15391541
where
15401542
Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
15411543
P: FnMut(&T) -> bool,
15421544
{
1545+
// FIXME: should we worry about the count overflowing? The only way to have more than
1546+
// `usize::MAX` mutable references is with ZSTs, which aren't useful to partition...
1547+
1548+
// These closure "factory" functions exist to avoid genericity in `Self`.
1549+
1550+
#[inline]
1551+
fn is_false<'a, T>(
1552+
predicate: &'a mut impl FnMut(&T) -> bool,
1553+
true_count: &'a mut usize,
1554+
) -> impl FnMut(&&mut T) -> bool + 'a {
1555+
move |x| {
1556+
let p = predicate(&**x);
1557+
*true_count += p as usize;
1558+
!p
1559+
}
1560+
}
1561+
1562+
#[inline]
1563+
fn is_true<T>(
1564+
predicate: &mut impl FnMut(&T) -> bool
1565+
) -> impl FnMut(&&mut T) -> bool + '_ {
1566+
move |x| predicate(&**x)
1567+
}
1568+
15431569
// Repeatedly find the first `false` and swap it with the last `true`.
1544-
while let Some(head) = self.find(|x| !predicate(x)) {
1545-
if let Some(tail) = self.rfind(|x| predicate(x)) {
1570+
let mut true_count = 0;
1571+
while let Some(head) = self.find(is_false(predicate, &mut true_count)) {
1572+
if let Some(tail) = self.rfind(is_true(predicate)) {
15461573
crate::mem::swap(head, tail);
1574+
true_count += 1;
15471575
} else {
15481576
break;
15491577
}
15501578
}
1579+
true_count
15511580
}
15521581

15531582
/// Checks if the elements of this iterator are partitioned according to the given predicate,

0 commit comments

Comments
 (0)