removeObjectsAtIndexes for Swift arrays

前端 未结 14 1185
长情又很酷
长情又很酷 2020-11-30 12:34

What is a Swift array equivalent to NSMutableArray\'s -removeObjectsAtIndexes:? Removing each index one by one doesn\'t work, as remaining indexes

相关标签:
14条回答
  • 2020-11-30 13:00

    one way is:

    var arrayB = arrayA.removeAtIndex(5)
    

    Another way is:

    var arr = ["I", "Love", "Life"]
    let slice = arr[1..<2]
    println(slice)
    //[Love]
    
    0 讨论(0)
  • 2020-11-30 13:01

    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!)
            })
    }
    
    0 讨论(0)
  • 2020-11-30 13:02

    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
            }
    }
    
    0 讨论(0)
  • 2020-11-30 13:03

    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)
        }
    }
    
    0 讨论(0)
  • 2020-11-30 13:05

    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.

    0 讨论(0)
  • 2020-11-30 13:09

    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)
        }
      }
    
    }
    
    0 讨论(0)
提交回复
热议问题