如何在Swift中从数组中删除元素


236

如何使用Apple的新语言Swift从数组中取消设置/删除元素?

这是一些代码:

let animals = ["cats", "dogs", "chimps", "moose"]

如何animals[2]从数组中删除元素?

Answers:


300

let关键字是声明不能改变的常量。如果要修改变量,则应var改用,例如:

var animals = ["cats", "dogs", "chimps", "moose"]

animals.remove(at: 2)  //["cats", "dogs", "moose"]

一个使原始集合保持不变的非变异替代方法是filter用于创建一个新集合,而无需删除想要删除的元素,例如:

let pets = animals.filter { $0 != "chimps" }

7
仅供参考:remove返回已删除的元素:let animal = animals.remove(at: 2)
2Toad

1
我们只能基于索引进行过滤吗?
shaqir

@shaqirsaiyed您可以过滤可以想到的任何谓词。例如,您可以过滤出所有以“ s”结尾的动物。
Womble

加动物=宠物
Puji Wahono

197

给定

var animals = ["cats", "dogs", "chimps", "moose"]

删除第一个元素

animals.removeFirst() // "cats"
print(animals)        // ["dogs", "chimps", "moose"]

删除最后一个元素

animals.removeLast() // "moose"
print(animals)       // ["cats", "dogs", "chimps"]

删除索引处的元素

animals.remove(at: 2) // "chimps"
print(animals)           // ["cats", "dogs", "moose"]

删除未知索引的元素

仅一个元素

if let index = animals.firstIndex(of: "chimps") {
    animals.remove(at: index)
}
print(animals) // ["cats", "dogs", "moose"]

对于多个元素

var animals = ["cats", "dogs", "chimps", "moose", "chimps"]

animals = animals.filter(){$0 != "chimps"}
print(animals) // ["cats", "dogs", "moose"]

笔记

  • 上面的方法在适当的位置修改了数组(除外filter),并返回已删除的元素。
  • 快速的Map Filter简化指南
  • 如果您不想修改原始阵列,则可以使用dropFirstdropLast创建一个新阵列。

更新到Swift 5.2


感谢这些示例,在您删除多个元素的未知索引 > chimps && moose的情况下,例如,您写什么闭包来删除?我正在寻找与众不同的东西{$0 != "chimps" && $0 != "moose"}

161

上面的答案似乎假设您知道要删除的元素的索引。

通常,您知道要在数组中删除的对象的引用。(例如,您遍历了数组并找到了它),在这种情况下,直接使用对象引用而不需要传递其索引的位置可能会更容易。因此,我建议这种解决方案。它使用身份运算符 !==,您可以使用该运算符来测试两个对象引用是否都引用同一对象实例。

func delete(element: String) {
    list = list.filter() { $0 !== element }
}

当然,这不仅适用于Strings。


23
应该是list = list.filter({ $0 != element })
Craig Grummitt 2015年

5
如果要与身份运算符联系,则不需要。
丹尼尔(Daniel)

3
array.indexOf({ $0 == obj })
jrc 2015年

2
请注意,如果其他对象引用list此删除操作,则不会更新其他数组引用,因为您正在将新数组分配给list。如果您使用这种方法从数组中删除,则只是一个隐含的含义。
Crashalot

1
函数式编程范例依赖于不可变的对象。即,您无需更改它们。而是,您创建一个新对象。这就是删除,映射,缩小等操作。列表将是一个新创建的对象。在上面的代码片段中,我分配回来列出一个新创建的对象。这对我有用,因为我以遵循函数式编程的方式设计代码。
丹尼尔(Daniel)

44

Swift 5: 这是一个很酷很容易的扩展,它无需过滤即可删除数组中的元素:

   extension Array where Element: Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        guard let index = firstIndex(of: object) else {return}
        remove(at: index)
    }

}

用法:

var myArray = ["cat", "barbecue", "pancake", "frog"]
let objectToRemove = "cat"

myArray.remove(object: objectToRemove) // ["barbecue", "pancake", "frog"]

也适用于其他类型,例如,Int因为Element是通用类型:

var myArray = [4, 8, 17, 6, 2]
let objectToRemove = 17

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]

1
有趣的数组元素:均衡部分
Nicolas Manzini

1
辉煌。尽管如果您先从协议列表开始就行不通,因为-协议类型不能符合'Equatable',因为只有具体类型才能符合协议:-(
AW101

22

对于Swift4:

list = list.filter{$0 != "your Value"}

15

从Xcode 10+开始,根据WWDC 2018会议223“拥抱算法”,一种不错的方法是mutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

苹果的例子:

var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]

phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."

请参阅Apple文档

因此,在OP的示例中,删除了动物[2],“黑猩猩”:

var animals = ["cats", "dogs", "chimps", "moose"]
animals.removeAll(where: { $0 == "chimps" } )
// or animals.removeAll { $0 == "chimps" }

此方法可能是首选,因为它可以很好地缩放(线性vs二次方),可读且干净。请记住,它仅在Xcode 10+中有效,在撰写本文时,它处于Beta中。


removeAll(where :)将仅能在快速4.2中执行
Vlad Pulichev

14

Swift中很少涉及数组

创建数组

var stringArray = ["One", "Two", "Three", "Four"]

在数组中添加对象

stringArray = stringArray + ["Five"]

从索引对象获取价值

let x = stringArray[1]

追加对象

stringArray.append("At last position")

在索引处插入对象

stringArray.insert("Going", atIndex: 1)

移除物件

stringArray.removeAtIndex(3)

Concat对象值

var string = "Concate Two object of Array \(stringArray[1]) + \(stringArray[2])"

14

你可以那样做。首先确保Dog数组中确实存在,然后将其删除。for如果您认为Dog数组中可能发生多次,请添加该语句。

var animals = ["Dog", "Cat", "Mouse", "Dog"]
let animalToRemove = "Dog"

for object in animals
{
    if object == animalToRemove{
        animals.removeAtIndex(animals.indexOf(animalToRemove)!)
    }
}

如果确定Dog在数组中退出并且仅发生一次,请执行以下操作:

animals.removeAtIndex(animals.indexOf(animalToRemove)!)

如果同时具有字符串和数字

var array = [12, 23, "Dog", 78, 23]
let numberToRemove = 23
let animalToRemove = "Dog"

for object in array
{

    if object is Int
    {
        // this will deal with integer. You can change to Float, Bool, etc...
        if object == numberToRemove
        {
        array.removeAtIndex(array.indexOf(numberToRemove)!)
        }
    }
    if object is String
    {
        // this will deal with strings
        if object == animalToRemove
        {
        array.removeAtIndex(array.indexOf(animalToRemove)!)
        }
    }
}

如果我的数组不包含字符串怎么办?
2016年

@apqu又做了一次更新'|| object == Int()'和'|| object == String()'是不必要的
GuiSoySauce

循环数组可以提高效率。检查.filter,.compactMap
MLBDG


10

使用索引数组删除元素:

  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. 整数数组

    let arrayResult = numbers.filter { element in
        return !indexesToRemove.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"]

4
这是一个简单的答案,它对于更好的编码和快速执行非常有效。
iOSDev

嗨@Krunal -伟大的答案,你可以看看下面的问题(从图像阵列释放图像):stackoverflow.com/questions/47735975/...
Server程序员

6

关于@Suragch的“删除未知索引的元素”的替代方案:

有一个更强大的“ indexOf(element)”版本,它将与谓词而不是对象本身匹配。它具有相同的名称,但由myObjects.indexOf {$ 0.property = valueToMatch}调用。它返回在myObjects数组中找到的第一个匹配项的索引。

如果该元素是一个对象/结构,则可能需要根据其属性之一的值删除该元素。例如,您有一个具有car.color属性的Car类,并且想要从carsArray中删除“红色”汽车。

if let validIndex = (carsArray.indexOf{$0.color == UIColor.redColor()}) {
  carsArray.removeAtIndex(validIndex)
}

可以预见的是,您可以通过将上面的if语句嵌入重复/循环循环中,并附加一个else块以将标志设置为“脱离”循环来删除“所有”红色汽车。


6

迅捷5

guard let index = orders.firstIndex(of: videoID) else { return }
orders.remove(at: index)

4

如果您有一组自定义对象,则可以按以下特定属性进行搜索:

    if let index = doctorsInArea.indexOf({$0.id == doctor.id}){
        doctorsInArea.removeAtIndex(index)
    }

或者例如您要按名称搜索

    if let index = doctorsInArea.indexOf({$0.name == doctor.name}){
        doctorsInArea.removeAtIndex(index)
    }

3

应该这样做(未经测试):

animals[2..3] = []

编辑:您需要将其设置为var,而不是let,否则它是一个不变的常量。


5
使用现有数组的(子)范围创建另一个数组时,该范围需要具有3个点。上面应该写成动物[2 ... 3]
zevij 2016年

3

我想出了以下扩展名Array,假定从Array实现中删除了元素,从而从中删除了元素Equatable

extension Array where Element: Equatable {

  mutating func removeEqualItems(item: Element) {
    self = self.filter { (currentItem: Element) -> Bool in
      return currentItem != item
    }
  }

  mutating func removeFirstEqualItem(item: Element) {
    guard var currentItem = self.first else { return }
    var index = 0
    while currentItem != item {
      index += 1
      currentItem = self[index]
    }
    self.removeAtIndex(index)
  }

}

用法:

var test1 = [1, 2, 1, 2]
test1.removeEqualItems(2) // [1, 1]

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]

: -嗨@nburk伟大的答案,你可以看看下面的问题(释放从图像阵列图像)stackoverflow.com/questions/47735975/...
Server程序员


1

我使用此扩展名,与Varun的扩展名几乎相同,但是此扩展名(如下)是通用的:

 extension Array where Element: Equatable  {
        mutating func delete(element: Iterator.Element) {
                self = self.filter{$0 != element }
        }
    }

1

从数组中删除元素,使用remove(at:)removeLast()removeAll()

yourArray = [1,2,3,4]

删除2位的值

yourArray.remove(at: 2)

从数组中删除最后一个值

yourArray.removeLast()

从集合中删除所有成员

yourArray.removeAll()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.