@@ -1513,6 +1513,7 @@ pub trait Iterator {
1513
1513
1514
1514
/// Reorder the elements of this iterator *in-place* according to the given predicate,
1515
1515
/// such that all those that return `true` precede all those that return `false`.
1516
+ /// Returns the number of `true` elements found.
1516
1517
///
1517
1518
/// The relative order of partitioned items is not maintained.
1518
1519
///
@@ -1529,25 +1530,53 @@ pub trait Iterator {
1529
1530
/// let mut a = [1, 2, 3, 4, 5, 6, 7];
1530
1531
///
1531
1532
/// // 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);
1533
1534
///
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
1536
1538
/// ```
1537
1539
#[ 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
1539
1541
where
1540
1542
Self : Sized + DoubleEndedIterator < Item = & ' a mut T > ,
1541
1543
P : FnMut ( & T ) -> bool ,
1542
1544
{
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
+
1543
1569
// 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) ) {
1546
1573
crate :: mem:: swap ( head, tail) ;
1574
+ true_count += 1 ;
1547
1575
} else {
1548
1576
break ;
1549
1577
}
1550
1578
}
1579
+ true_count
1551
1580
}
1552
1581
1553
1582
/// Checks if the elements of this iterator are partitioned according to the given predicate,
0 commit comments