Swift 数组删除元素

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift 数组删除元素相关的知识,希望对你有一定的参考价值。

参考技术A Swift 数组里提供了删除数组元素的方法主要包括以下几种:

1、@inlinable public mutating func remove(at index: Int) -> Element
通过索引删除元素,且索引必须是数组有效索引,返回删除所索引元素。

复杂度为 O(n)
remove(at index: Int)示例

var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
let removed = measurements.remove(at: 2)
print(measurements)
// Prints "[1.1, 1.5, 1.2, 1.5, 1.3, 1.2]"

@inlinable public mutating func removeAll(keepingCapacity keepCapacity: Bool = false)

删除数组所有元素
参数keepCapacity 为true保持当前数组容量,默认值为false。

复杂度为O(n)

Swift数组如果要删除某个元素,那么我们有哪些方式呢?

一个简单的方法是我们通过filter直接过滤掉我们需要生成的元素:

let ar = [2, 3, 5, 34]
// 生成新数组
let ar2 = ar.filter( 0 != 7)
print(ar3)
但是这种方法会生成一个新的数组,如果我们不想生成一个新的数组,还在原来的数组上操作该怎么做呢?

一、使用removeAll(where:)
@inlinable public mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows
使用这个方法删除数组中的每一个匹配的元素
复杂度为O(n)
removeAll(where:)示例:

删除数组中的奇数

var numbers = [5, 6, 7, 8, 9, 10, 11]
numbers.removeAll(where: $0 % 2 != 0 )
// numbers == [6, 8, 10]
删除数组中的某个元素

var ar = [2, 3, 2, 5, 34]
ar.removeAll(where: $0==2)
// ar = [3, 5, 34]
二、使用remove(at:)
思路大概就是找到需要删除数组索引进行删除,在OC里我们可以通过indexOfObject:方法获取索引,在Swift里我们可以通过以下方法获取索引:

1、index(of:)获取数组里元素出现的第一个索引,但是从Swift5.0开始,这个方法被废弃了。

@inlinable public func index(of element: Element) -> Int?
2、firstIndex(of:)在使用firstIndex(of :)查找特定元素的位置。

@inlinable public func firstIndex(of element: Element) -> Int?
firstIndex(of:)使用示例:

var students = ["Ben", "Ivy", "Jordell", "Maxime"]
if let i = students.firstIndex(of: "Maxime")
students[i] = "Max"

print(students)
// Prints "["Ben", "Ivy", "Jordell", "Max"]"
OK,接下来我们来进行对原数组操作进行元素删除:

var ar = [2, 3, 5, 34]

// 原数组操作
// 删除元素 3
if let index = ar.firstIndex(of: 3)
ar.remove(at: index)

// 测试删除未含元素
if let index = ar.firstIndex(of: 6)
ar.remove(at: index)

写在最后:
使用方法一可以把所有需要删除的元素删除,使用方法二可以删除第一个目标元素。当然也可以使用lastIndex(of: )删除最后一个目标元素。

链接: https://www.jianshu.com/p/1c6da474af89

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

【中文标题】如何在 Swift 中从数组中删除一个元素【英文标题】:How to remove an element from an array in Swift 【发布时间】:2014-07-25 22:35:36 【问题描述】:

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

这里有一些代码:

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

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

【问题讨论】:

【参考方案1】:

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

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

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

当然,这不仅适用于Strings。

【讨论】:

应该是list = list.filter( $0 != element ) 如果您想与身份操作员核实,则不要。 array.indexOf( $0 == obj ) 请注意,如果其他对象引用list,则此删除不会更新其他数组引用,因为您将新数组分配给list。如果您使用这种方法从数组中删除,这只是一个微妙的暗示。 函数式编程范式依赖于不可变对象。即,您不会更改它们。相反,您创建了一个新对象。这就是 delete、map、reduce 等所做的。 list 将是一个新创建的对象。在上面的代码 sn-p 中,我分配回列出一个新创建的对象。这对我有用,因为我以遵循函数式编程的方式设计我的代码。【参考方案2】:

如果你有自定义对象数组,你可以像这样按特定属性搜索:

if let index = doctorsInArea.firstIndex(where: $0.id == doctor.id)
    doctorsInArea.remove(at: index)

或者如果您想按名称搜索,例如

if let index = doctorsInArea.firstIndex(where: $0.name == doctor.name)
    doctorsInArea.remove(at: index)

【讨论】:

我认为的最佳答案【参考方案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.remove(at: 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 - 很好的答案,你能看看以下问题(从图像数组中释放图像):***.com/questions/47735975/… 这是最干净的解决方案。【参考方案4】:

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

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

for object in animals 
    if object == animalToRemove 
        animals.remove(at: animals.firstIndex(of: animalToRemove)!)
    

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

animals.remove(at: animals.firstIndex(of: 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.remove(at: array.firstIndex(of: numberToRemove)!)
        
    
    if object is String 
        // this will deal with strings
        if object == animalToRemove 
        array.remove(at: array.firstIndex(of: animalToRemove)!)
        
    

【讨论】:

如果我的数组不包含字符串怎么办? @apqu 做了另一个更新' ||对象 == Int()' 和 '|| object == String()' 是不必要的 循环数组会降低效率。检查 .filter、.compactMap【参考方案5】:

如果您不知道要删除的元素的索引,并且该元素符合 Equatable 协议,您可以这样做:

animals.remove(at: animals.firstIndex(of: "dogs")!)

查看 Equatable 协议答案:How do I do indexOfObject or a proper containsObject

【讨论】:

【参考方案6】:

Swift 中很少有与数组相关的操作

创建数组

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

在数组中添加对象

stringArray = stringArray + ["Five"]

从索引对象中获取值

let x = stringArray[1]

追加对象

stringArray.append("At last position")

在索引处插入对象

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

删除对象

stringArray.remove(at: 3)

连接对象值

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

【讨论】:

stringArray += ["Five"] 或者更好的是stringArray += CollectionOfOne("Five")【参考方案7】:

应该这样做(未测试):

animals[2...3] = []

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

【讨论】:

当使用现有数组的(子)范围创建另一个数组时,范围需要有 3 个点。以上应该写成动物[2...3] Array 符合RangeReplaceableCollection 协议,它提供了一个完全用于此目的的方法animals.removeSubrange(2...3) 请注意,此答案中的代码删除了两个元素,即索引 2 和 3 处的元素。如果只想删除索引 2 处的元素,可以使用2..<3.【参考方案8】:

给定

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 除外)并返回被移除的元素。 Swift Guide to Map Filter Reduce 如果不想修改原有数组,可以使用dropFirstdropLast新建数组。

更新到 Swift 5.2

【讨论】:

感谢这些例子,在你 删除未知索引的元素 > 对于多个元素,你会写什么闭包来删除chimps && moose实例?我正在寻找不同于 $0 != "chimps" && $0 != "moose" 的东西【参考方案9】:

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

yourArray = [1,2,3,4]

移除2位置的值

yourArray.remove(at: 2)

从数组中删除最后一个值

yourArray.removeLast()

从集合中删除所有成员

yourArray.removeAll()

【讨论】:

【参考方案10】:

斯威夫特 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]

【讨论】:

有趣的这个数组 where Element: Equatable part 太棒了。虽然如果你从一个协议列表开始它不起作用,因为——协议类型不能符合'Equatable',因为只有具体类型才能符合协议:-( 我喜欢这个解决方案,因为它涵盖了删除属于结构数组的元素 我正在寻找 Objective-C 等效的删除函数。这个答案最适合那个。谢谢。【参考方案11】:

斯威夫特 5

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

【讨论】:

【参考方案12】:

从 Xcode 10+ 开始,根据 WWDC 2018 session 223, "Embracing Algorithms,",一个好的方法是 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's Documentation

所以在 OP 的例子中,移除动物[2],“黑猩猩”:

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

这种方法可能是首选,因为它可以很好地扩展(线性与二次),可读且干净。请记住,它仅适用于 Xcode 10+,并且在撰写本文时处于 Beta 版中。

【讨论】:

removeAll(where:) 只能在 swift 4.2 中使用 phrase.removeAll(where: vowels.contains)【参考方案13】:

对于 Swift4:

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

【讨论】:

这将删除每个匹配的元素,而不仅仅是一个。让 theArray = ["A", "B", "C", "A"] 让 newArray = theArray.filter($0 != "A") 结果 newArray == ["B", "C"] 【参考方案14】:

使用索引数组删除元素:

    字符串和索引数组

    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"]
    

    整数和索引数组

    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]
    

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

    整数数组

    let arrayResult = numbers.filter  element in
        return !indexesToRemove.contains(element)
    
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    

    字符串数组

    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"]
    

【讨论】:

这是一个线性答案,它对于更好的编码和快速执行非常有效。 嗨@Krunal - 很好的答案,你能看看以下问题(从图像数组中释放图像):***.com/questions/47735975/…【参考方案15】:

我使用这个扩展,几乎和 Varun 的一样,但是这个(下)是通用的:

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

【讨论】:

【参考方案16】:

删除字符串对象的扩展

extension Array 
    mutating func delete(element: String) 
        self = self.filter()  $0 as! String != element 
    

【讨论】:

强制展开会导致崩溃,我认为在这种情况下你应该避免它。 什么是“变异”函数? 它曾经告诉这个函数会改变self(array)。【参考方案17】:

let 关键字用于声明不能更改的常量。如果你想修改一个变量,你应该使用var,例如:

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

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

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

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

【讨论】:

仅供参考:remove 返回删除的元素:let animal = animals.remove(at: 2) 我们可以只根据索引过滤吗?? @shaqirsaiyed 您可以过滤您能想到的任何谓词。例如你可以过滤掉所有以“s”结尾的动物。 添加动物 = 宠物 remove(at:) 让我在 swift 5 中获得一个单品?【参考方案18】:

关于@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 语句嵌入到重复/while 循环中并附加一个 else 块来设置一个标志以“中断”循环,从而删除“所有”红色汽车。

【讨论】:

以上是关于Swift 数组删除元素的主要内容,如果未能解决你的问题,请参考以下文章

在 SpriteKit/Swift 中从数组中删除元素

Swift 3 数组 - 在其他数组的帮助下删除多个元素

Swift:像在 Lua 中一样快速从数组中删除元素

如何删除 Swift 数组中的所有 nil 元素?

iOS swift从另一个数组中删除一个数组的元素

在 Swift 中从数组中删除重复元素