Make it Swifter Challenge

Today’s challenge is courtesy of the Swift Users email list, posted by Adriano Ferreira. His starting point is here, where he was really looking to simplify chained calls. But making things Swifter isn’t always just about making chaining look better.

func selectionSort(_ array: [Int]) -> [Int] {

    guard array.count > 1, let minElement = array.min() else {
        return array
    }

    let indexOfMinElement = array.index(of: minElement)!

    // All of this just to filter out the first smallest element and return the rest
    // Also tried ‘suffix(from:)' here, but couldn’t make it work properly
    let rest = array.enumerated()
                    .filter({ index, _ in index != indexOfMinElement })
                    .map({ _, element in element })

    return [minElement] + selectionSort(rest)
}

What can make this Swifter?

First, practicality. Even though any array of 0 or 1 elements is already sorted, I don’t think adding code to test for those conditions is practical. I think it’s better just to streamline and let the code run, even if the case of one element isn’t perfectly ideal.

Second, flow. I don’t like the idea of first finding the minimum and then finding its index. Enumeration allows these operations to be run in tandem.

Third, style. Enumeration should really return (index: Index, value: Element) tuples. It doesn’t. So I took this opportunity to extend Array to create the kind of tuples I’d rather work with. Because of that, my solution is more complex than it really needs to be (for a sorting function no one ever actually uses) because I’d rather use code that handles $0.value and $1.index than $0.1 and $1.0.

My redesigned code is here. Share yours!

5 Comments

  • How about this? The generic constraints are murder, but I think the actual method itself is quite nice.

    • Beautiful! (Well, other than no spaces before and after `<` on the compare... 🙂 )

      • I’m horrified I missed that

        • Spaces before and after ..<, spaces after commas...

  • Today I learned about the maxSplits parameter of split, which led me to this implementation.