Removing from an array during enumeration in Swift?

I want to list an array in Swift and remove specific elements. I wonder if it is safe to do this, and if not, how should I achieve it.

Currently I will do this:

for (index, aString: String) in enumerate(array) { //Some of the strings... array.removeAtIndex(index) } 
+76
arrays ios enumeration swift
04 Feb '15 at 14:28
source share
7 answers

In Swift 2, it's pretty simple using enumerate and reverse .

 var a = [1,2,3,4,5,6] for (i,num) in a.enumerate().reverse() { a.removeAtIndex(i) } print(a) 

See my swiftstub here: http://swiftstub.com/944024718/?v=beta

+63
Oct. 14 '15 at 3:57
source share

You can consider filter method:

 var theStrings = ["foo", "bar", "zxy"] // Filter only strings that begins with "b" theStrings = theStrings.filter { $0.hasPrefix("b") } 

The filter parameter is just a closure that takes an instance of an array type (in this case, String ) and returns a Bool . When the result is true , it saves the element, otherwise the element is filtered out.

+55
Feb 04 '15 at 14:40
source share

In Swift 3 and 4, this will be:

With numbers, according to Johnston's answer:

 var a = [1,2,3,4,5,6] for (i,num) in a.enumerated().reversed() { a.remove(at: i) } print(a) 

With strings as an OP question:

 var b = ["a", "b", "c", "d", "e", "f"] for (i,str) in b.enumerated().reversed() { if str == "c" { b.remove(at: i) } } print(b) 

However, now in Swift 4.2 and later there is even a better, faster way that Apple recommended in WWDC2018:

 var c = ["a", "b", "c", "d", "e", "f"] c.removeAll(where: {$0 == "c"}) print(c) 

This new method has several advantages:

  1. This is faster than filter implementations.
  2. This eliminates the need to access arrays.
  3. It removes elements in place and thus updates the original array, rather than placing and returning a new array.
+32
Jan 01 '16 at 17:24
source share

When an element from a specific index is removed from the array, all subsequent elements will change their position (and index), because they move back one position.

So, the best way is to move around the array in reverse order - in which case, I suggest using the traditional for loop:

 for var index = array.count - 1; index >= 0; --index { if condition { array.removeAtIndex(index) } } 

However, in my opinion, the best approach is to use the filter method as described in his @perlfly answer.

+13
Feb 04 '15 at 14:45
source share

No, it is not safe to mutate arrays during rewriting, your code will work.

If you want to delete only a few objects, you can use the filter function.

+4
Feb 04 '15 at 14:40
source share

Or create a mutable array to store the items that you want to remove, and then, after listing, remove these items from the original. Or create a copy of the array (immutable), list it and remove objects (not by index) from the original when listing.

+2
Feb 04 '15 at 14:45
source share

I recommend setting the elements to nil during enumeration and, upon completion, deleting all empty elements using the array () array () method.

+1
Feb 04 '15 at 14:43
source share



All Articles