Skip to content

Commit 5f42bd8

Browse files
committed
Add custom implementations of removeLast and remove(at:) to Array
1 parent 7ded7fe commit 5f42bd8

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

stdlib/public/core/Arrays.swift.gyb

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,17 +1493,6 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
14931493
}
14941494

14951495
%if Self == 'ArraySlice':
1496-
/// Removes and returns the last element of the array.
1497-
///
1498-
/// The array must not be empty. This example removes the last number from an
1499-
/// array of `Double` values.
1500-
///
1501-
/// var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
1502-
/// let removed = measurements.removeLast()
1503-
/// print(measurements)
1504-
/// // Prints "[1.1, 1.5, 2.9, 1.2, 1.5, 1.3]"
1505-
///
1506-
/// - Returns: The element that was removed.
15071496
@_inlineable
15081497
public mutating func _customRemoveLast() -> Element? {
15091498
_precondition(count > 0, "Can't removeLast from an empty ${Self}")
@@ -1519,33 +1508,55 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
15191508
self.replaceSubrange((i &- 1)..<i, with: EmptyCollection())
15201509
return result
15211510
}
1522-
%end
1523-
1524-
/// Inserts a new element at the specified position.
1525-
///
1526-
/// The new element is inserted before the element currently at the specified
1527-
/// index. If you pass the array's `endIndex` property as the `index`
1528-
/// parameter, the new element is appended to the array.
1511+
1512+
/// Removes and returns the element at the specified position.
15291513
///
1530-
/// var numbers = [1, 2, 3, 4, 5]
1531-
/// numbers.insert(100, at: 3)
1532-
/// numbers.insert(200, at: numbers.endIndex)
1514+
/// All the elements following the specified position are moved up to
1515+
/// close the gap.
15331516
///
1534-
/// print(numbers)
1535-
/// // Prints "[1, 2, 3, 100, 4, 5, 200]"
1517+
/// var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
1518+
/// let removed = measurements.remove(at: 2)
1519+
/// print(measurements)
1520+
/// // Prints "[1.1, 1.5, 1.2, 1.5, 1.3, 1.2]"
15361521
///
1537-
/// - Parameter newElement: The new element to insert into the array.
1538-
/// - Parameter i: The position at which to insert the new element.
1539-
/// `index` must be a valid index of the array or equal to its `endIndex`
1540-
/// property.
1522+
/// - Parameter index: The position of the element to remove. `index` must
1523+
/// be a valid index of the array.
1524+
/// - Returns: The element at the specified index.
15411525
///
15421526
/// - Complexity: O(*n*), where *n* is the length of the array.
15431527
@_inlineable
1544-
public mutating func insert(_ newElement: Element, at i: Int) {
1545-
_checkIndex(i)
1546-
self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
1528+
@discardableResult
1529+
public mutating func remove(at index: Int) -> Element {
1530+
_checkIndex(index)
1531+
let result = self[index]
1532+
self.replaceSubrange(index..<(index + 1), with: EmptyCollection())
1533+
return result
1534+
}
1535+
1536+
%else:
1537+
/// Removes and returns the last element of the array.
1538+
///
1539+
/// - Returns: The last element of the array if the array is not empty;
1540+
/// otherwise, `nil`.
1541+
///
1542+
/// - Complexity: O(*n*) if the array is bridged, where *n* is the length
1543+
/// of the array; otherwise, O(1).
1544+
@_inlineable
1545+
public mutating func popLast() -> Element? {
1546+
guard !isEmpty else { return nil }
1547+
return _customRemoveLast()!
15471548
}
15481549

1550+
@_inlineable
1551+
public mutating func _customRemoveLast() -> Element? {
1552+
_precondition(!isEmpty, "Can't removeLast from an empty ${Self}")
1553+
_makeUniqueAndReserveCapacityIfNotUnique()
1554+
let newCount = _getCount() - 1
1555+
let pointer = (_buffer.firstElementAddress + newCount)
1556+
let element = pointer.move()
1557+
_buffer.count = newCount
1558+
return element
1559+
}
15491560
/// Removes and returns the element at the specified position.
15501561
///
15511562
/// All the elements following the specified position are moved up to
@@ -1564,10 +1575,41 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol {
15641575
@_inlineable
15651576
@discardableResult
15661577
public mutating func remove(at index: Int) -> Element {
1567-
let result = self[index]
1568-
self.replaceSubrange(index..<(index + 1), with: EmptyCollection())
1578+
_checkIndex(index)
1579+
_makeUniqueAndReserveCapacityIfNotUnique()
1580+
let newCount = _getCount() - 1
1581+
let pointer = (_buffer.firstElementAddress + index)
1582+
let result = pointer.move()
1583+
pointer.moveInitialize(from: pointer + 1, count: newCount - index)
1584+
_buffer.count = newCount
15691585
return result
15701586
}
1587+
%end
1588+
1589+
/// Inserts a new element at the specified position.
1590+
///
1591+
/// The new element is inserted before the element currently at the specified
1592+
/// index. If you pass the array's `endIndex` property as the `index`
1593+
/// parameter, the new element is appended to the array.
1594+
///
1595+
/// var numbers = [1, 2, 3, 4, 5]
1596+
/// numbers.insert(100, at: 3)
1597+
/// numbers.insert(200, at: numbers.endIndex)
1598+
///
1599+
/// print(numbers)
1600+
/// // Prints "[1, 2, 3, 100, 4, 5, 200]"
1601+
///
1602+
/// - Parameter newElement: The new element to insert into the array.
1603+
/// - Parameter i: The position at which to insert the new element.
1604+
/// `index` must be a valid index of the array or equal to its `endIndex`
1605+
/// property.
1606+
///
1607+
/// - Complexity: O(*n*), where *n* is the length of the array.
1608+
@_inlineable
1609+
public mutating func insert(_ newElement: Element, at i: Int) {
1610+
_checkIndex(i)
1611+
self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
1612+
}
15711613

15721614
/// Removes all elements from the array.
15731615
///
@@ -2358,35 +2400,6 @@ extension Array {
23582400
}
23592401
#endif
23602402

2361-
extension Array {
2362-
/// Removes and returns the last element of the array.
2363-
///
2364-
/// - Returns: The last element of the array if the array is not empty;
2365-
/// otherwise, `nil`.
2366-
///
2367-
/// - Complexity: O(*n*) if the array is bridged, where *n* is the length
2368-
/// of the array; otherwise, O(1).
2369-
@_inlineable
2370-
public mutating func popLast() -> Element? {
2371-
guard !isEmpty else { return nil }
2372-
return removeLast()
2373-
}
2374-
}
2375-
2376-
extension ContiguousArray {
2377-
/// Removes and returns the last element of the array.
2378-
///
2379-
/// - Returns: The last element of the array if the array is not empty;
2380-
/// otherwise, `nil`.
2381-
///
2382-
/// - Complexity: O(1)
2383-
@_inlineable
2384-
public mutating func popLast() -> Element? {
2385-
guard !isEmpty else { return nil }
2386-
return removeLast()
2387-
}
2388-
}
2389-
23902403
extension ArraySlice {
23912404
@_inlineable
23922405
public // @testable

0 commit comments

Comments
 (0)