What is a Swift array equivalent to NSMutableArray
\'s -removeObjectsAtIndexes:
? Removing each index one by one doesn\'t work, as remaining indexes
one way is:
var arrayB = arrayA.removeAtIndex(5)
Another way is:
var arr = ["I", "Love", "Life"]
let slice = arr[1..<2]
println(slice)
//[Love]
I used Swift's filter
function:
func removeMusicListAtIndexes(idxSet: NSIndexSet) {
if idxSet.containsIndex(selectedMusic) {
selectedMusic = -1;
}
musicList = musicList.filter({
var idx = find(self.musicList, $0)
// If a value isn't in the index, it isn't being removed
return !idxSet.containsIndex(idx!)
})
}
I have not tested this, but I would bet that a non-mutating version is faster if it copies contiguous subranges. Something like:
extension Array {
public func removing(indices indicesToRemove: IndexSet) -> Self {
guard let lastIndex = indicesToRemove.last else {
return self
}
assert(lastIndex <= (self.count - 1), message: "Index set contains out of bounds indices")
var result = Self()
result.reserveCapacity(self.count - indicesToRemove.count)
let indicesToKeep = IndexSet(self.indices).subtracting(indicesToRemove)
let rangesToKeep = indicesToKeep.rangeView
rangesToKeep.forEach { (range) in
result.append(contentsOf: self[range])
}
return result
}
}
To complete Ethan's answer, C-loop styles will be deprecated in Swift 3.0. Here's then a Swift 3.0 compatible answer:
mutating func removeAtIndexes(indexes: NSIndexSet) {
var i = indexes.lastIndex
while i != NSNotFound {
self.removeAtIndex(i)
i = indexes.indexLessThanIndex(i)
}
}
Another expansion on Ethan's answer (trimmed down from what I have in my own framework):
extension Array {
// Code taken from https://stackoverflow.com/a/26174259/1975001
// Further adapted to work with Swift 2.2
/// Removes objects at indexes that are in the specified `NSIndexSet`.
/// - parameter indexes: the index set containing the indexes of objects that will be removed
public mutating func removeAtIndexes(indexes: NSIndexSet) {
for i in indexes.reverse() {
self.removeAtIndex(i)
}
}
}
This version uses NSIndexSet
's SequenceType
extension provided by Swift's Foundation bridge.
edit: Also, newer versions of Swift (Don't remember which one added it) have a struct
type called IndexSet
, which can be bridged to/from NSIndexSet
. And can be reverse()
d like NSIndexSet
.
I ended up doing it this way:
According to Apple's documentation on NSIndexSet, "index sets store indexes as sorted ranges". So we could enumerate over the given NSIndexSet
backwards and remove the element from the array at each index one by one, like so:
extension Array {
mutating func removeAtIndexes(indexes: NSIndexSet) {
for var i = indexes.lastIndex; i != NSNotFound; i = indexes.indexLessThanIndex(i) {
self.removeAtIndex(i)
}
}
}