Skip to content

Commit e58bfae

Browse files
authored
Merge pull request #1 from klaaspieter/remove
Complete set of removal methods for SortedArray
2 parents fce7626 + f09bc66 commit e58bfae

File tree

2 files changed

+183
-9
lines changed

2 files changed

+183
-9
lines changed

Sources/SortedArray.swift

+109
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,115 @@ extension SortedArray: CustomStringConvertible, CustomDebugStringConvertible {
116116
}
117117
}
118118

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+
119228
// MARK: - More efficient variants of default implementations or implementations that need fewer constraints than the default implementations.
120229
extension SortedArray {
121230
/// Returns the first index where the specified value appears in the collection.

Tests/SortedArrayTests/SortedArrayTests.swift

+74-9
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,73 @@ class SortedArrayTests: XCTestCase {
152152
XCTAssertEqual(description, "<SortedArray> [\"a\", \"b\", \"c\"]")
153153
}
154154

155-
func testFilterReturnsSortedArray() {
156-
let source = SortedArray(unsorted: [3,2,1])
157-
let sut = source.filter { $0 % 2 == 0 }
158-
XCTAssert(type(of: sut) == SortedArray<Int>.self)
155+
func testFilter() {
156+
let sut = SortedArray(unsorted: ["a", "b", "c"])
157+
assertElementsEqual(sut.filter { $0 != "a" }, ["b", "c"])
159158
}
160159

161-
func testFilterMaintainsSortOrder() {
162-
let sut = SortedArray(unsorted: ["b", "a", "c", "a", "d", "A"])
163-
assertElementsEqual(sut.filter { $0 != "a" }, ["A", "b", "c", "d"])
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)
164165
}
165166

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() {
206+
var sut = SortedArray(unsorted: 1...3)
207+
sut.remove(1)
208+
assertElementsEqual(sut, [2,3])
209+
}
210+
211+
func testRemoveElementInMiddlePreservesSortOrder() {
212+
var sut = SortedArray(unsorted: 1...5)
213+
sut.remove(4)
214+
assertElementsEqual(sut, [1,2,3,5])
215+
}
216+
217+
func testRemoveElementAtEndPreservesSortOrder() {
218+
var sut = SortedArray(unsorted: 1...3)
219+
sut.remove(3)
220+
assertElementsEqual(sut, [1,2])
221+
}
166222
}
167223

168224
extension SortedArrayTests {
@@ -191,8 +247,17 @@ extension SortedArrayTests {
191247
("testMax", testMax),
192248
("testCustomStringConvertible", testCustomStringConvertible),
193249
("testCustomDebugStringConvertible", testCustomDebugStringConvertible),
194-
("testFilterReturnsSortedArray", testFilterReturnsSortedArray),
195-
("testFilterMaintainsSortOrder", testFilterMaintainsSortOrder),
250+
("testFilter", testFilter),
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),
196261
]
197262
}
198263
}

0 commit comments

Comments
 (0)