Is there no easy way to remove a specific element from an array, if it is equal to a given string? The workarounds are to find the index of the element of the array you wish to remove, and then removeAtIndex
, or to create a new array where you append all elements that are not equal to the given string. But is there no quicker way?

- 2,405
- 5
- 21
- 41
-
1Have you looked at the methods in the NSMutableArray class reference, like removeObject:, or removeObjectIdenticalTo:? – rdelmar Jan 10 '15 at 17:12
-
I am using swift, and the way I find out what I can do with an array, is to put a dot after its name and see what options xcode suggests, these include removeAll, removeAtIndex, removeLast, and removeRange. I can't see any reference to removeObjectIdenticalTo. – TimWhiting Jan 10 '15 at 19:32
-
1Your question didn't specify whether you were referring to a Swift Array or an NSMutableArray; you can use ether in Swift. If you're programming in Swift, you won't see the NSMutableArray suggestions unless you cast your array to an NSMutableArray – rdelmar Jan 10 '15 at 20:23
-
1Thanks, I only started programming a month ago so that is very helpful – TimWhiting Jan 11 '15 at 00:00
9 Answers
You can use filter() to filter your array as follow
var strings = ["Hello","Playground","World"]
strings = strings.filter { $0 != "Hello" }
print(strings) // "["Playground", "World"]\n"
edit/update:
Xcode 10 • Swift 4.2 or later
You can use the new RangeReplaceableCollection
mutating method called removeAll(where:)
var strings = ["Hello","Playground","World"]
strings.removeAll { $0 == "Hello" }
print(strings) // "["Playground", "World"]\n"
If you need to remove only the first occurrence of an element we ca implement a custom remove method on RangeReplaceableCollection
constraining the elements to Equatable
:
extension RangeReplaceableCollection where Element: Equatable {
@discardableResult
mutating func removeFirst(_ element: Element) -> Element? {
guard let index = firstIndex(of: element) else { return nil }
return remove(at: index)
}
}
Or using a predicate for non Equatable
elements:
extension RangeReplaceableCollection {
@discardableResult
mutating func removeFirst(where predicate: @escaping (Element) throws -> Bool) rethrows -> Element? {
guard let index = try firstIndex(where: predicate) else { return nil }
return remove(at: index)
}
}
var strings = ["Hello","Playground","World"]
strings.removeFirst("Hello")
print(strings) // "["Playground", "World"]\n"
strings.removeFirst { $0 == "Playground" }
print(strings) // "["World"]\n"

- 229,809
- 59
- 489
- 571
Using filter like suggested above is nice. But if you want to remove only one occurrence of a value or you assume there are no duplicates in the array and you want a faster algorithm, use this:
EDIT: Swift 5 Update
if let index = array.firstIndex(of: "stringToRemove") {
array.remove(at: index)
} else {
// not found
}
Thanks @Thomas Mary.
Swift 3 and 4
if let index = array.index(of: "stringToRemove") {
array.remove(at: index)
} else {
// not found
}

- 1,048
- 12
- 37
-
1Swift 5 update : `if let index = array.firstIndex(of: "stringToRemove") { array.remove(at: index) }` – Thomas Mary Aug 07 '20 at 09:59
It's not clear if by quicker you mean in terms of execution time or amount of code.
In the latter case you can easily create a copy using the filter
method. For example, given the following array:
let array = ["1", "2", "3", "4", "5"]
you can create a copy with all elements but "2" as:
let filteredArray = array.filter { $0 != "2" }

- 71,651
- 11
- 148
- 165
-
2
-
7@LeonardoSavioDabus: Haha, yes, but I was interrupted by my wife asking me a question while writing the answer... so I won ;-) – Antonio Jan 10 '15 at 17:17
-
1Thanks, I guess this is essentially what I have been doing, by using a for loop to go through the array and append the element to another array if it is not equal to the string I wish to remove, and when I said quicker, you're right I just mean looks tidier in my code. Thanks! – TimWhiting Jan 10 '15 at 19:29
You'll want to use filter()
. If you have a single element (called say obj
) to remove, then the filter()
predicate will be { $0 != obj }
. If you do this repeatedly for a large array this might be a performance issue. If you can defer removing individual objects and want to remove an entire sub-array then use something like:
var stringsToRemove : [String] = ...
var strings : [String] = ...
strings.filter { !contains(stringsToRemove, $0) }
for example:
1> ["a", "b", "c", "d"].filter { !contains(["b", "c"], $0) }
$R5: [String] = 2 values {
[0] = "a"
[1] = "d"
}

- 67,920
- 20
- 95
- 145
You could use filter() in combination with operator overloading to produce an easily repeatable solution:
func -= (inout left: [String], right: String){
left = left.filter{$0 != right}
}
var myArrayOfStrings:[String] = ["Hello","Playground","World"]
myArrayOfStrings -= "Hello"
print(myArrayOfStrings) // "[Playground, World]"

- 71
- 5
if you need to delete subArray from array then this is a perfect solution using Swift3:
var array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
let subArrayToDelete = ["c", "d", "e", "ee"]
array = array.filter{ !subArrayToDelete.contains($0) }
print(array) // ["a", "b", "f", "g", "h", "i", "j"]
this is better for your performance rather than deleting one by one.
btw even faster solution is (but it will rearrange items in the final array):
array = Array(Set(array).subtracting(subArrayToDelete))

- 7,899
- 4
- 56
- 63
var ra = ["a", "ab", "abc", "a", "ab"]
print(ra) // [["a", "ab", "abc", "a", "ab"]
ra.removeAll(where: { $0 == "a" })
print(ra) // ["ab", "abc", "ab"]

- 252
- 3
- 3
Simple loop over Array
var array = ["Apple","Banana","Orange"]
for (index,value) in array.enumerated(){
if value == "Banana"{
array.remove(at: index)
}

- 622
- 10
- 15
-
-
Thanks Buddy @LeoDabus for correcting me i have changed from let to var now you able to do it – Threadripper Aug 24 '20 at 06:48
One small point.
Normally you must simply use .filter{$0 != target}
If for some reason you wish to traverse the array. It's a basic of programming that you DON'T edit/delete items from an array while you're traversing it as, depending on the exact nature of the language/OS/etc it may or may not result in unpredictable behavior for the obvious reasons.
The only safe way to traverse is (in some cases) backwards but (always) using a while formulation which re-looks at the array each pass:
while let found = urls.firstIndex(of: target) {
urls.remove(at: found)
}
This is a basic of working with arrays.
Again, always use .filter{$0 != target}
As a footnote, in the incredible case that it is a performance issue (literally 10s of millions of entries), you'd handle the whole thing completely differently using indices and so on, so it is totally irrelevant to this question.

- 27,874
- 70
- 431
- 719