Removing object from array in Swift 3
Solution 1
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"}
Solution 2
var a = ["one", "two", "three", "four", "five"]
// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }
Solution 3
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)
}
Solution 4
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)
Solution 5
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")
Related videos on Youtube
Comments
-
Kamlesh Shingarakhiya over 2 years
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'
-
Paulw11 over 7 yearsYou can use a
Set<Contact>
rather than an Array. Can you provide more information about your contact object? If you have made it yourself you will need it to conform toHashable
andEquatable
in order to put it in a set
-
-
zeeple about 7 yearsThis is the best answer, but it is beyond stupid not to have a remove(object: "beta").
-
Ryan X about 7 yearsenumerated -> filter -> map and remove(at) is smart solution. Recommend this one
-
Michael almost 7 yearsThat is the correct Swift solution, that makes use of syntax goodies offered by the language.
-
Adam Waite over 6 yearsI think
.index(of:
is only available if the collection containsEquatable
types. -
vadian over 6 years@AdamWaite Yes but this applies also to the Foundation types.
-
Irshad Mohamed over 6 yearswill this work if I want to remove multiple objects? like (where: {$0 == "beta" || $0 == "gamma" })
-
juancazalla almost 6 yearsThis isn't right, what if you have more than one "beta"? This only works if the array does not contain more than one occurrences. The right answer is using a filter or running this answer in a while,
while let index = array.index(of: "beta") { array.remove(at: index) }
-
vadian almost 6 years@juancazalla You are right but in the case if the array can contain more than one occurrence use the
filter
solution. But if the objects are unique use alwaysindex(of
because it's much more performant thanfilter
-
juancazalla almost 6 yearsThis only works if the array does not contain more than one occurrences. The right answer is using a filter or running this answer in a while. As a user of this extension, I expect it to remove all the occurrences and not only one
-
Radek Wilczak over 5 yearsIt's nice, but it should be
remove(element: Element)
because in Array you can store also types like Int, Double - they are not objects. -
bibscy over 5 years@vadian I've read that you are a musician too and I was wondering if you could help me out with an answer stackoverflow.com/questions/53349969 . Many thanks
-
TomSawyer about 5 yearsWhat if item is an object?
-
jeet.chanchawat about 5 yearsArgument labels '(where:)' do not match any available overloads
-
Renetik about 5 years@jeet.chanchawat well probably different swift version then ... Oh this question was for 3 ? Well I think I had 4.2 at time of writing but don't remember now, will check it later, it definitely worked for me
-
Mike Taverne over 4 years@TomSawyer to filter out an object, use $0 !==