21

是否可以同时使用索引位置从数组中删除多个项目 .remove(at: i) 有点像:

伪代码:

myArray.remove(at: 3, 5, 8, 12)

如果是这样,这样做的语法是什么?


更新

我正在尝试这个,它有效,但是下面答案中的扩展更具可读性和合理性,并且实现了与伪代码完全相同的目标。

创建一个“位置”数组:[3, 5, 8, 12]

let sorted = positions.sorted(by: { $1 < $0 })
for index in sorted
{
    myArray.remove(at: index)
}
4

6 回答 6

37

如果索引是连续的使用removeSubrange方法是可能的。例如,如果您想删除索引 3 到 5 处的项目:

myArray.removeSubrange(ClosedRange(uncheckedBounds: (lower: 3, upper: 5)))

对于非连续索引,我建议将索引较大的项目删除为较小的项目。除了代码可以更短之外,我可以想到在单行中“同时”删除项目没有任何好处。您可以使用扩展方法来做到这一点:

extension Array {
  mutating func remove(at indexes: [Int]) {
    for index in indexes.sorted(by: >) {
      remove(at: index)
    }
  }
}

然后:

myArray.remove(at: [3, 5, 8, 12])

更新:使用上面的解决方案,您需要确保索引数组不包含重复的索引。或者您可以避免重复如下:

extension Array {
    mutating func remove(at indexes: [Int]) {
        var lastIndex: Int? = nil
        for index in indexes.sorted(by: >) {
            guard lastIndex != index else {
                continue
            }
            remove(at: index)
            lastIndex = index
        }
    }
}


var myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
myArray.remove(at: [5, 3, 5, 12]) // duplicated index 5
// result: [0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 13] only 3 elements are removed
于 2016-10-11T10:32:42.087 回答
24

使用数组元素的索引删除元素:

  1. 字符串和索引数组

    let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
    let indexAnimals = [0, 3, 4]
    let arrayRemainingAnimals = animals
        .enumerated()
        .filter { !indexAnimals.contains($0.offset) }
        .map { $0.element }
    
    print(arrayRemainingAnimals)
    
    //result - ["dogs", "chimps", "cow"]
    
  2. 整数和索引数组

    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let indexesToRemove = [3, 5, 8, 12]
    
    numbers = numbers
        .enumerated()
        .filter { !indexesToRemove.contains($0.offset) }
        .map { $0.element }
    
    print(numbers)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    



使用另一个数组的元素值删除元素

  1. 整数数组

    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let elementsTobeRemoved = [3, 5, 8, 12]
    let arrayResult = numbers.filter { element in
        return !elementsTobeRemoved.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    
  2. 字符串数组

    let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
    let arrayRemoveLetters = ["a", "e", "g", "h"]
    let arrayRemainingLetters = arrayLetters.filter {
        !arrayRemoveLetters.contains($0)
    }
    
    print(arrayRemainingLetters)
    
    //result - ["b", "c", "d", "f", "i"]
    
于 2017-03-18T08:31:05.860 回答
9

简单明了的解决方案,只需Array扩展:

extension Array {

    mutating func remove(at indices: [Int]) {
        Set(indices)
            .sorted(by: >)
            .forEach { rmIndex in
                self.remove(at: rmIndex)
            }
    }
}
  • Set(indices)- 确保唯一性
  • .sorted(by: >)- 函数从最后一个到第一个删除元素,因此在删除过程中我们确定索引是正确的
于 2018-06-08T10:22:07.003 回答
6

斯威夫特 4

extension Array {

    mutating func remove(at indexs: [Int]) {
        guard !isEmpty else { return }
        let newIndexs = Set(indexs).sorted(by: >)
        newIndexs.forEach {
            guard $0 < count, $0 >= 0 else { return }
            remove(at: $0)  
        }
    }

}

var arr = ["a", "b", "c", "d", "e", "f"]

arr.remove(at: [2, 3, 1, 4])

result: ["a", "f"]
于 2018-06-21T06:11:53.377 回答
2

您可以创建一组要删除的索引。

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let indexSet = [3, 5, 8, 12]
indexSet.reversed().forEach{ array.remove(at: $0) }
print(array)

输出:[0, 1, 2, 4, 6, 7, 9, 10, 11]

如果索引是连续的,则使用removeSubrange

array.removeSubrange(1...3) /// Will remove the elements from 1, 2 and 3 positions.
于 2018-04-16T11:39:48.787 回答
1

根据NSMutableArrayAPI,我建议将索引实现为IndexSet.

你只需要颠倒顺序。

extension Array {

    mutating func remove(at indexes: IndexSet) {
        indexes.reversed().forEach{ self.remove(at: $0) }
    }
}

另请参阅this answer提供更有效的算法。

于 2018-03-26T05:04:53.817 回答