Reputation: 2777
In my application I added one object in array when select cell and unselect and remove object when re-select cell. I used that code but give me error.
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])
}
}
It gives me 2 error like that:
C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'
Upvotes: 110
Views: 135124
Reputation: 34175
Swift Remove object from array
In Swift 3 and Swift 4
var array = ["a", "b", "c", "d", "e", "f"]
for (index, element) in array.enumerated().reversed() {
array.remove(at: index)
}
From Swift 4.2 you can use more advanced approach(faster and memory efficient)
array.removeAll(where: { $0 == "c" })
instead of
array = array.filter { !$0.hasPrefix("c") }
Read more here
Upvotes: 4
Reputation: 285069
The Swift equivalent to NSMutableArray
's removeObject
is:
var array = ["alpha", "beta", "gamma"]
if let index = array.firstIndex(of: "beta") {
array.remove(at: index)
}
if the objects are unique. There is no need at all to cast to NSArray
and use indexOfObject:
The API index(of:
also works but this causes an unnecessary implicit bridge cast to NSArray
.
Of course you can write an extension of RangeReplaceableCollection
to emulate the function. But due to value semantics you cannot name it removeObject
.
extension RangeReplaceableCollection where Element : Equatable {
@discardableResult
mutating func remove(_ element : Element) -> Element?
{
if let index = firstIndex(of: element) {
return remove(at: index)
}
return nil
}
}
Like remove(at:
it returns the removed item or nil
if the array doesn't contain the item.
If there are multiple occurrences of the same object use filter
. However in cases like data source arrays where an index is associated with a particular object firstIndex(of
is preferable because it's faster than filter
.
Update:
In Swift 4.2+ you can remove one or multiple occurrences of beta
with removeAll(where:)
:
array.removeAll{$0 == "beta"}
Upvotes: 202
Reputation: 403
This is what I've used (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)
Results:
["A", "B", "D", "C", "B", "D"]
["A", "B", "C", "B", "D"]
["A", "B", "C", "D"]
Important: The array from which you remove items must contain Equatable elements (such as objects, strings, number, etc.)
Upvotes: 0
Reputation: 3141
In Swift 5, Use this Extension
:
extension Array where Element: Equatable{
mutating func remove (element: Element) {
if let i = self.firstIndex(of: element) {
self.remove(at: i)
}
}
}
example:
var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")
In Swift 3, Use this Extension
:
extension Array where Element: Equatable{
mutating func remove (element: Element) {
if let i = self.index(of: element) {
self.remove(at: i)
}
}
}
example:
var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")
Upvotes: 15
Reputation: 6373
Extension for array to do it easily and allow chaining for Swift 4.2 and up:
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
}
}
Upvotes: 1
Reputation: 1364
This is official answer to find index of specific object, then you can easily remove any object using that index :
var students = ["Ben", "Ivy", "Jordell", "Maxime"]
if let i = students.firstIndex(of: "Maxime") {
// students[i] = "Max"
students.remove(at: i)
}
print(students)
// Prints ["Ben", "Ivy", "Jordell"]
Here is the link: https://developer.apple.com/documentation/swift/array/2994720-firstindex
Upvotes: 1
Reputation: 9923
for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object)
is for loop in C-style and has been removed
Change your code to something like this to remove all similar object if it have looped:
let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
for index in indexes.reversed() {
arrContacts.remove(at: index)
}
Upvotes: 6
Reputation: 2338
Swift 4
var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
students.remove(at: index)
}
Upvotes: 5
Reputation: 7155
For Swift 3, you can use index(where:) and include a closure that does the comparison of an object in the array ($0) with whatever you are looking for.
var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
array.remove(at: index)
}
Upvotes: 26
Reputation: 2811
var a = ["one", "two", "three", "four", "five"]
// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }
Upvotes: 74
Reputation: 21520
Another nice and useful solution is to create this kind of extension:
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
}
}
In this way, if you have your array with custom objects:
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)
Upvotes: 17
Reputation: 41
The correct and working one-line solution for deleting a unique object (named "objectToRemove") from an array of these objects (named "array") in Swift 3 is:
if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
array.remove(at: index)
}
Upvotes: 4
Reputation: 2425
Try this in Swift 3
array.remove(at: Index)
Instead of
array.removeAtIndex(index)
Update
"Declaration is only valid at file scope".
Make sure the object is in scope. You can give scope "internal", which is default.
index(of:<Object>)
to work, class should conform to Equatable
Upvotes: 1