在Swift 3中从数组中删除对象


92

在我的应用程序在阵列中加入一个对象时选择单元和非选择和删除对象时重新选择小区。我使用了该代码,但给了我错误。

extension Array {
    func indexOfObject(object : AnyObject) -> NSInteger {
        return (self as NSArray).indexOfObject(object)
    }

    mutating func removeObject(object : AnyObject) {
        for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
            self.removeAtIndex(index)
        }
    }
}

class MyViewController: UITableViewController {
    var arrContacts: [Any] = []
    var contacts: [Any] = []

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        arrContacts.removeObject(contacts[indexPath.row])
    }
}

它给了我2像这样的错误:

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'

您可以使用Set<Contact>而不是数组。您能否提供有关您的联系对象的更多信息?如果你自己做它,你会需要它符合HashableEquatable以把它放在一个组
Paulw11

Answers:


164

雨燕等同NSMutableArrayremoveObject是:

var array = ["alpha", "beta", "gamma"]

if let index = array.firstIndex(of: "beta") {
    array.remove(at: index)
}

如果对象是唯一的。完全没有必要强制NSArray使用indexOfObject:

该APIindex(of:也可以使用,但这会导致不必要的隐式桥强制转换为NSArray

如果同一对象多次出现,请使用filter。但是,在像数据源数组这样的情况下,将索引与特定对象相关联firstIndex(of是可取的,因为它比快filter

更新:

在斯威夫特4.2+你可以删除一个或多次出现betaremoveAll(where:)

array.removeAll{$0 == "beta"}

33
这是最好的答案,但愚蠢的是没有remove(object:“ beta”)。
zeeple

5
我认为.index(of: 仅当集合包含Equatable类型时才可用。
亚当·怀特

@AdamWaite是的,但这也适用于Foundation类型。
vadian

这是不对的,如果您有多个“测试版”怎么办?仅当数组中不止一个事件出现时,此方法才起作用。正确的答案是使用过滤器或在一段时间内运行此答案,while let index = array.index(of: "beta") { array.remove(at: index) }
juancazalla

@juancazalla是的,但是如果数组可以包含多个事件,请使用filter解决方案。但是,如果对象是唯一的,则总是使用index(of它,因为它的性能要比filter
vadian

71
var a = ["one", "two", "three", "four", "five"]

// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }

7
那是正确的Swift解决方案,它利用了该语言提供的语法功能。
迈克尔”

1
如果项目是对象怎么办?
TomSawyer

@TomSawyer筛选出一个对象,使用$ 0!==
Mike Taverne

25

对于Swift 3,您可以使用index(where :)并包括一个闭包,该闭包将数组中的对象($ 0)与所需的内容进行比较。

var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
  array.remove(at: index)
}

如果要删除多个对象,此方法是否可以工作?like(其中:{$ 0 ==“ beta” || $ 0 ==“ gamma”})
Irshad Mohamed

16

另一个不错且有用的解决方案是创建这种扩展:

extension Array where Element: Equatable {

    @discardableResult mutating func remove(object: Element) -> Bool {
        if let index = index(of: object) {
            self.remove(at: index)
            return true
        }
        return false
    }

    @discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
        if let index = self.index(where: { (element) -> Bool in
            return predicate(element)
        }) {
            self.remove(at: index)
            return true
        }
        return false
    }

}

这样,如果您的数组中包含自定义对象:

let obj1 = MyObject(id: 1)
let obj2 = MyObject(id: 2)
var array: [MyObject] = [obj1, obj2]

array.remove(where: { (obj) -> Bool in
    return obj.id == 1
})
// OR
array.remove(object: obj2) 

1
仅当数组中不止一个事件出现时,此方法才起作用。正确的答案是使用过滤器或在一段时间内运行此答案。作为此扩展程序的用户,我希望它会删除所有出现的内容,而不仅仅是一个
-juancazalla

很好,但这应该是remove(element: Element)因为在Array中您还可以存储Int,Double等类型,它们不是对象。
Radek Wilczak

8

Swift 5中,使用以下命令Extension

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.firstIndex(of: element) {
            self.remove(at: i)
        }
    }
}

例:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

Swift 3中,使用以下命令Extension

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.index(of: element) {
            self.remove(at: i)
        }
    }
}

例:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

6
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) 是C风格的for循环,已被删除

  2. 将您的代码更改为如下所示,以删除所有类似的对象(如果已循环):

    let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
    for index in indexes.reversed() {
       arrContacts.remove(at: index)
    }
    

枚举->过滤器->映射并删除(at)是明智的解决方案。推荐这个
Ryan X

4

斯威夫特4

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
   students.remove(at: index)
}

3

在Swift 3中,从这些对象的数组(名为“ array”)中删除唯一对象(名为“ objectToRemove”)的正确且可行的单行解决方案是:

if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
   array.remove(at: index)
}

1

在Swift 3中尝试

array.remove(at: Index)

代替

array.removeAtIndex(index)

更新资料

"Declaration is only valid at file scope".

确保对象在范围内。您可以给范围“内部”,这是默认设置。

index(of:<Object>) 工作,上课应符合 Equatable


1

Swift 3和4中

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

for (index, element) in array.enumerated().reversed() {
    array.remove(at: index)
}

Swift 4.2中,您可以使用更高级的方法(更快,内存效率更高)

array.removeAll(where: { $0 == "c" })

代替

array = array.filter { !$0.hasPrefix("c") }

在这里阅读更多


1

扩展数组很容易做到,并允许Swift 4.2及更高版本链接:

public extension Array where Element: Equatable {
    @discardableResult
    public mutating func remove(_ item: Element) -> Array {
        if let index = firstIndex(where: { item == $0 }) {
            remove(at: index)
        }
        return self
    }

    @discardableResult
    public mutating func removeAll(_ item: Element) -> Array {
        removeAll(where: { item == $0 })
        return self
    }
}

参数标签'(where :)'与任何可用的重载都不匹配
jeet.chanchawat

1
@ jeet.chanchawat可能是不同的Swift版本,那么...哦,这个问题是3个?好吧,我认为在撰写本文时我有4.2,但现在不记得了,稍后再检查,它肯定对我
有用


0

这就是我用过的(Swift 5)...

    extension Array where Element:Equatable
    {
        @discardableResult
        mutating func removeFirst(_ item:Any ) -> Any? {
            for index in 0..<self.count {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
            }
            return nil
        }
        @discardableResult
        mutating func removeLast(_ item:Any ) -> Any? {
            var index = self.count-1
            while index >= 0 {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
                index -= 1
            }
            return nil
        }
    }

    var arrContacts:[String] = ["A","B","D","C","B","D"]
    var contacts: [Any] = ["B","D"]
    print(arrContacts)
    var index = 1
    arrContacts.removeFirst(contacts[index])
    print(arrContacts)
    index = 0
    arrContacts.removeLast(contacts[index])
    print(arrContacts)

结果:

   ["A", "B", "D", "C", "B", "D"]
   ["A", "B", "C", "B", "D"]
   ["A", "B", "C", "D"]

重要说明:从中删除项目的数组必须包含Equatable元素(例如对象,字符串,数字等)

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.