Silverpoint
A journal written in Swift by Hugo A.G

Removing an object with an unknown index from an array

Today's extension will introduce a utility function for removing objects with an unknown index from an array. There are multiple ways to go about doing this in Swift so I've decided to show three different approaches as well as my preferred way (as of the writing of this post).

TLDR; Give me the code

For those of you who just wan't the good stuff, here's the way I like to do this currently.

extension Array where Element: Equatable {
    mutating func remove(_ object: Element) {
        guard let index = firstIndex(of: object) else { return }
        remove(at: index)
    }
}

Setting up your extension

To apply to any and all types of arrays, we're going to first be creating an extension for the Array type and apply the generic clause stating that each Element must conform to the Equatable protocol.

This allows us to target any types of arrays that store comparable objects in them. With reference types such as classes, you can conform to the Equatable protocol to determine how two objects of the same class are the same.

The next step is to provide our remove function which will handle the operation. It's important to make this function mutating so that it also covers value types like structs.

The extension and function signature should look something like this.

extension Array where Element: Equatable {
    mutating func remove(_ object: Element) { }
}

Now we can fill up the function body.

Method 1

The first method involves finding the index of the object in question and then removing the object using that index.

guard let index = firstIndex(of: object) else { return }
remove(at: index)

I like this method because I can dictate what behavior to occur easily in the event that the object in question isn't found, inside the guard return block.

Method 2

The other way you can handle this is by creating a new array from the existing array that filters out the object in question, and assigning it to the current array.

self = self.filter(){$0 != object}

I relied on the closure shorthand syntax to handle the filter operation. I personally don't like to rely on this method because of the fact that we're creating a new array from the existing one. For most general cases it's probably OK to do this, but if you have an array with thousands of beefy items, you'll probably notice the impact.

Method 3

The last method is really just a nicer version of the first one, that relies more on the shorthand closure syntax as well as the Swift mapping function to transform the resultant index of the object in question, if it finds one. Because the index retrieved from the firstIndex is an optional, this guarantees that the contents of the mapping function will execute if it does find one.

self.firstIndex(of: object).map { self.remove(at: $0) }
Tagged with: