Skip to content

Commit f09bc66

Browse files
committed
Complete set of remove... methods
1 parent 74da27c commit f09bc66

2 files changed

Lines changed: 167 additions & 14 deletions

File tree

Sources/SortedArray.swift

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,6 @@ public struct SortedArray<Element> {
5757
_elements.append(contentsOf: newElements)
5858
_elements.sort(by: areInIncreasingOrder)
5959
}
60-
61-
/// Removes an element from the array, preserving the sort order.
62-
///
63-
/// - Complexity: O(_n_), where _n_ is the size of the array.
64-
public mutating func remove(_ element: Element) {
65-
guard let index = index(of: element) else { return }
66-
_elements.remove(at: index)
67-
}
6860
}
6961

7062
extension SortedArray where Element: Comparable {
@@ -124,6 +116,115 @@ extension SortedArray: CustomStringConvertible, CustomDebugStringConvertible {
124116
}
125117
}
126118

119+
// MARK: - Removing elements. This is mostly a reimplementation of part `RangeReplaceableCollection`'s interface. `SortedArray` can't conform to `RangeReplaceableCollection` because some of that protocol's semantics (e.g. `append(_:)` don't fit `SortedArray`'s semantics.
120+
extension SortedArray {
121+
/// Removes and returns the element at the specified position.
122+
///
123+
/// - Parameter index: The position of the element to remove. `index` must be a valid index of the array.
124+
/// - Returns: The element at the specified index.
125+
/// - Complexity: O(_n_), where _n_ is the length of the array.
126+
public mutating func remove(at index: Int) -> Element {
127+
return _elements.remove(at: index)
128+
}
129+
130+
/// Removes the elements in the specified subrange from the array.
131+
///
132+
/// - Parameter bounds: The range of the array to be removed. The
133+
/// bounds of the range must be valid indices of the array.
134+
///
135+
/// - Complexity: O(_n_), where _n_ is the length of the array.
136+
public mutating func removeSubrange(_ bounds: Range<Int>) {
137+
_elements.removeSubrange(bounds)
138+
}
139+
140+
/// Removes the elements in the specified subrange from the array.
141+
///
142+
/// - Parameter bounds: The range of the array to be removed. The
143+
/// bounds of the range must be valid indices of the array.
144+
///
145+
/// - Complexity: O(_n_), where _n_ is the length of the array.
146+
public mutating func removeSubrange(_ bounds: ClosedRange<Int>) {
147+
_elements.removeSubrange(bounds)
148+
}
149+
150+
/// Removes the elements in the specified subrange from the array.
151+
///
152+
/// - Parameter bounds: The range of the array to be removed. The
153+
/// bounds of the range must be valid indices of the array.
154+
///
155+
/// - Complexity: O(_n_), where _n_ is the length of the array.
156+
public mutating func removeSubrange(_ bounds: CountableRange<Int>) {
157+
_elements.removeSubrange(bounds)
158+
}
159+
160+
/// Removes the elements in the specified subrange from the array.
161+
///
162+
/// - Parameter bounds: The range of the array to be removed. The
163+
/// bounds of the range must be valid indices of the array.
164+
///
165+
/// - Complexity: O(_n_), where _n_ is the length of the array.
166+
public mutating func removeSubrange(_ bounds: CountableClosedRange<Int>) {
167+
_elements.removeSubrange(bounds)
168+
}
169+
170+
/// Removes the specified number of elements from the beginning of the
171+
/// array.
172+
///
173+
/// - Parameter n: The number of elements to remove from the array.
174+
/// `n` must be greater than or equal to zero and must not exceed the
175+
/// number of elements in the array.
176+
///
177+
/// - Complexity: O(_n_), where _n_ is the length of the array.
178+
public mutating func removeFirst(_ n: Int) {
179+
_elements.removeFirst(n)
180+
}
181+
182+
/// Removes and returns the first element of the array.
183+
///
184+
/// - Precondition: The array must not be empty.
185+
/// - Returns: The removed element.
186+
/// - Complexity: O(_n_), where _n_ is the length of the collection.
187+
public mutating func removeFirst() -> Element {
188+
return _elements.removeFirst()
189+
}
190+
191+
/// Removes and returns the last element of the array.
192+
///
193+
/// - Precondition: The collection must not be empty.
194+
/// - Returns: The last element of the collection.
195+
/// - Complexity: O(1)
196+
public mutating func removeLast() -> Element {
197+
return _elements.removeLast()
198+
}
199+
200+
/// Removes the given number of elements from the end of the array.
201+
///
202+
/// - Parameter n: The number of elements to remove. `n` must be greater
203+
/// than or equal to zero, and must be less than or equal to the number of
204+
/// elements in the array.
205+
/// - Complexity: O(1).
206+
public mutating func removeLast(_ n: Int) {
207+
_elements.removeLast(n)
208+
}
209+
210+
/// Removes all elements from the array.
211+
///
212+
/// - Parameter keepCapacity: Pass `true` to keep the existing capacity of the array after removing its elements. The default value is `false`.
213+
///
214+
/// - Complexity: O(_n_), where _n_ is the length of the array.
215+
public mutating func removeAll(keepingCapacity keepCapacity: Bool = true) {
216+
_elements.removeAll(keepingCapacity: keepCapacity)
217+
}
218+
219+
/// Removes an element from the array. If the array contains multiple instances of `element`, this method only removes the first one.
220+
///
221+
/// - Complexity: O(_n_), where _n_ is the size of the array.
222+
public mutating func remove(_ element: Element) {
223+
guard let index = index(of: element) else { return }
224+
_elements.remove(at: index)
225+
}
226+
}
227+
127228
// MARK: - More efficient variants of default implementations or implementations that need fewer constraints than the default implementations.
128229
extension SortedArray {
129230
/// Returns the first index where the specified value appears in the collection.

Tests/SortedArrayTests/SortedArrayTests.swift

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,19 +157,64 @@ class SortedArrayTests: XCTestCase {
157157
assertElementsEqual(sut.filter { $0 != "a" }, ["b", "c"])
158158
}
159159

160-
func testRemoveAtBeginningPreservesSortOrder() {
160+
func testRemoveAtIndex() {
161+
var sut = SortedArray(unsorted: [3,4,2,1])
162+
let removedElement = sut.remove(at: 1)
163+
assertElementsEqual(sut, [1,3,4])
164+
XCTAssertEqual(removedElement, 2)
165+
}
166+
167+
func testRemoveSubrange() {
168+
var sut = SortedArray(unsorted: ["a","d","c","b"])
169+
sut.removeSubrange(2..<4)
170+
assertElementsEqual(sut, ["a","b"])
171+
}
172+
173+
func testRemoveFirst() {
174+
var sut = SortedArray(unsorted: [3,4,2,1])
175+
let removedElement = sut.removeFirst()
176+
assertElementsEqual(sut, [2,3,4])
177+
XCTAssertEqual(removedElement, 1)
178+
}
179+
180+
func testRemoveFirstN() {
181+
var sut = SortedArray(unsorted: [3,4,2,1])
182+
sut.removeFirst(2)
183+
assertElementsEqual(sut, [3,4])
184+
}
185+
186+
func testRemoveLast() {
187+
var sut = SortedArray(unsorted: [3,4,2,1])
188+
let removedElement = sut.removeLast()
189+
assertElementsEqual(sut, [1,2,3])
190+
XCTAssertEqual(removedElement, 4)
191+
}
192+
193+
func testRemoveLastN() {
194+
var sut = SortedArray(unsorted: [3,4,2,1])
195+
sut.removeLast(2)
196+
assertElementsEqual(sut, [1,2])
197+
}
198+
199+
func testRemoveAll() {
200+
var sut = SortedArray(unsorted: ["a","d","c","b"])
201+
sut.removeAll()
202+
assertElementsEqual(sut, [])
203+
}
204+
205+
func testRemoveElementAtBeginningPreservesSortOrder() {
161206
var sut = SortedArray(unsorted: 1...3)
162207
sut.remove(1)
163208
assertElementsEqual(sut, [2,3])
164209
}
165210

166-
func testRemoveInMiddlePreservesSortOrder() {
211+
func testRemoveElementInMiddlePreservesSortOrder() {
167212
var sut = SortedArray(unsorted: 1...5)
168213
sut.remove(4)
169214
assertElementsEqual(sut, [1,2,3,5])
170215
}
171216

172-
func testRemoveAtEndPreservesSortOrder() {
217+
func testRemoveElementAtEndPreservesSortOrder() {
173218
var sut = SortedArray(unsorted: 1...3)
174219
sut.remove(3)
175220
assertElementsEqual(sut, [1,2])
@@ -203,9 +248,16 @@ extension SortedArrayTests {
203248
("testCustomStringConvertible", testCustomStringConvertible),
204249
("testCustomDebugStringConvertible", testCustomDebugStringConvertible),
205250
("testFilter", testFilter),
206-
("testRemoveAtBeginningPreservesSortOrder", testRemoveAtBeginningPreservesSortOrder),
207-
("testRemoveInMiddlePreservesSortOrder", testRemoveInMiddlePreservesSortOrder),
208-
("testRemoveAtEndPreservesSortOrder", testRemoveAtEndPreservesSortOrder),
251+
("testRemoveAtIndex", testRemoveAtIndex),
252+
("testRemoveSubrange", testRemoveSubrange),
253+
("testRemoveFirst", testRemoveFirst),
254+
("testRemoveFirstN", testRemoveFirstN),
255+
("testRemoveLast", testRemoveLast),
256+
("testRemoveLastN", testRemoveLastN),
257+
("testRemoveAll", testRemoveAll),
258+
("testRemoveElementAtBeginningPreservesSortOrder", testRemoveElementAtBeginningPreservesSortOrder),
259+
("testRemoveElementInMiddlePreservesSortOrder", testRemoveElementInMiddlePreservesSortOrder),
260+
("testRemoveElementAtEndPreservesSortOrder", testRemoveElementAtEndPreservesSortOrder),
209261
]
210262
}
211263
}

0 commit comments

Comments
 (0)