@@ -1402,6 +1402,178 @@ impl<T> [T] {
14021402 sort:: quicksort ( self , |a, b| f ( a) . lt ( & f ( b) ) ) ;
14031403 }
14041404
1405+ /// Moves all consecutive repeated elements to the end of the slice according to the
1406+ /// [`PartialEq`] trait implementation.
1407+ ///
1408+ /// Returns two slices. The first contains no consecutive repeated elements.
1409+ /// The second contains all the duplicates in no specified order.
1410+ ///
1411+ /// If the slice is sorted, the first returned slice contains no duplicates.
1412+ ///
1413+ /// # Examples
1414+ ///
1415+ /// ```
1416+ /// #![feature(slice_partition_dedup)]
1417+ ///
1418+ /// let mut slice = [1, 2, 2, 3, 3, 2, 1, 1];
1419+ ///
1420+ /// let (dedup, duplicates) = slice.partition_dedup();
1421+ ///
1422+ /// assert_eq!(dedup, [1, 2, 3, 2, 1]);
1423+ /// assert_eq!(duplicates, [2, 3, 1]);
1424+ /// ```
1425+ #[ unstable( feature = "slice_partition_dedup" , issue = "54279" ) ]
1426+ #[ inline]
1427+ pub fn partition_dedup ( & mut self ) -> ( & mut [ T ] , & mut [ T ] )
1428+ where T : PartialEq
1429+ {
1430+ self . partition_dedup_by ( |a, b| a == b)
1431+ }
1432+
1433+ /// Moves all but the first of consecutive elements to the end of the slice satisfying
1434+ /// a given equality relation.
1435+ ///
1436+ /// Returns two slices. The first contains no consecutive repeated elements.
1437+ /// The second contains all the duplicates in no specified order.
1438+ ///
1439+ /// The `same_bucket` function is passed references to two elements from the slice and
1440+ /// must determine if the elements compare equal. The elements are passed in opposite order
1441+ /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is moved
1442+ /// at the end of the slice.
1443+ ///
1444+ /// If the slice is sorted, the first returned slice contains no duplicates.
1445+ ///
1446+ /// # Examples
1447+ ///
1448+ /// ```
1449+ /// #![feature(slice_partition_dedup)]
1450+ ///
1451+ /// let mut slice = ["foo", "Foo", "BAZ", "Bar", "bar", "baz", "BAZ"];
1452+ ///
1453+ /// let (dedup, duplicates) = slice.partition_dedup_by(|a, b| a.eq_ignore_ascii_case(b));
1454+ ///
1455+ /// assert_eq!(dedup, ["foo", "BAZ", "Bar", "baz"]);
1456+ /// assert_eq!(duplicates, ["bar", "Foo", "BAZ"]);
1457+ /// ```
1458+ #[ unstable( feature = "slice_partition_dedup" , issue = "54279" ) ]
1459+ #[ inline]
1460+ pub fn partition_dedup_by < F > ( & mut self , mut same_bucket : F ) -> ( & mut [ T ] , & mut [ T ] )
1461+ where F : FnMut ( & mut T , & mut T ) -> bool
1462+ {
1463+ // Although we have a mutable reference to `self`, we cannot make
1464+ // *arbitrary* changes. The `same_bucket` calls could panic, so we
1465+ // must ensure that the slice is in a valid state at all times.
1466+ //
1467+ // The way that we handle this is by using swaps; we iterate
1468+ // over all the elements, swapping as we go so that at the end
1469+ // the elements we wish to keep are in the front, and those we
1470+ // wish to reject are at the back. We can then split the slice.
1471+ // This operation is still O(n).
1472+ //
1473+ // Example: We start in this state, where `r` represents "next
1474+ // read" and `w` represents "next_write`.
1475+ //
1476+ // r
1477+ // +---+---+---+---+---+---+
1478+ // | 0 | 1 | 1 | 2 | 3 | 3 |
1479+ // +---+---+---+---+---+---+
1480+ // w
1481+ //
1482+ // Comparing self[r] against self[w-1], this is not a duplicate, so
1483+ // we swap self[r] and self[w] (no effect as r==w) and then increment both
1484+ // r and w, leaving us with:
1485+ //
1486+ // r
1487+ // +---+---+---+---+---+---+
1488+ // | 0 | 1 | 1 | 2 | 3 | 3 |
1489+ // +---+---+---+---+---+---+
1490+ // w
1491+ //
1492+ // Comparing self[r] against self[w-1], this value is a duplicate,
1493+ // so we increment `r` but leave everything else unchanged:
1494+ //
1495+ // r
1496+ // +---+---+---+---+---+---+
1497+ // | 0 | 1 | 1 | 2 | 3 | 3 |
1498+ // +---+---+---+---+---+---+
1499+ // w
1500+ //
1501+ // Comparing self[r] against self[w-1], this is not a duplicate,
1502+ // so swap self[r] and self[w] and advance r and w:
1503+ //
1504+ // r
1505+ // +---+---+---+---+---+---+
1506+ // | 0 | 1 | 2 | 1 | 3 | 3 |
1507+ // +---+---+---+---+---+---+
1508+ // w
1509+ //
1510+ // Not a duplicate, repeat:
1511+ //
1512+ // r
1513+ // +---+---+---+---+---+---+
1514+ // | 0 | 1 | 2 | 3 | 1 | 3 |
1515+ // +---+---+---+---+---+---+
1516+ // w
1517+ //
1518+ // Duplicate, advance r. End of slice. Split at w.
1519+
1520+ let len = self . len ( ) ;
1521+ if len <= 1 {
1522+ return ( self , & mut [ ] )
1523+ }
1524+
1525+ let ptr = self . as_mut_ptr ( ) ;
1526+ let mut next_read: usize = 1 ;
1527+ let mut next_write: usize = 1 ;
1528+
1529+ unsafe {
1530+ // Avoid bounds checks by using raw pointers.
1531+ while next_read < len {
1532+ let ptr_read = ptr. add ( next_read) ;
1533+ let prev_ptr_write = ptr. add ( next_write - 1 ) ;
1534+ if !same_bucket ( & mut * ptr_read, & mut * prev_ptr_write) {
1535+ if next_read != next_write {
1536+ let ptr_write = prev_ptr_write. offset ( 1 ) ;
1537+ mem:: swap ( & mut * ptr_read, & mut * ptr_write) ;
1538+ }
1539+ next_write += 1 ;
1540+ }
1541+ next_read += 1 ;
1542+ }
1543+ }
1544+
1545+ self . split_at_mut ( next_write)
1546+ }
1547+
1548+ /// Moves all but the first of consecutive elements to the end of the slice that resolve
1549+ /// to the same key.
1550+ ///
1551+ /// Returns two slices. The first contains no consecutive repeated elements.
1552+ /// The second contains all the duplicates in no specified order.
1553+ ///
1554+ /// If the slice is sorted, the first returned slice contains no duplicates.
1555+ ///
1556+ /// # Examples
1557+ ///
1558+ /// ```
1559+ /// #![feature(slice_partition_dedup)]
1560+ ///
1561+ /// let mut slice = [10, 20, 21, 30, 30, 20, 11, 13];
1562+ ///
1563+ /// let (dedup, duplicates) = slice.partition_dedup_by_key(|i| *i / 10);
1564+ ///
1565+ /// assert_eq!(dedup, [10, 20, 30, 20, 11]);
1566+ /// assert_eq!(duplicates, [21, 30, 13]);
1567+ /// ```
1568+ #[ unstable( feature = "slice_partition_dedup" , issue = "54279" ) ]
1569+ #[ inline]
1570+ pub fn partition_dedup_by_key < K , F > ( & mut self , mut key : F ) -> ( & mut [ T ] , & mut [ T ] )
1571+ where F : FnMut ( & mut T ) -> K ,
1572+ K : PartialEq ,
1573+ {
1574+ self . partition_dedup_by ( |a, b| key ( a) == key ( b) )
1575+ }
1576+
14051577 /// Rotates the slice in-place such that the first `mid` elements of the
14061578 /// slice move to the end while the last `self.len() - mid` elements move to
14071579 /// the front. After calling `rotate_left`, the element previously at index
0 commit comments