Sorting nil Dates to the end of an Array

Viewed 2700

Trying to sort an array in Swift in descending order. This works well

objectArray.sort{ $0.date!.compare($1.date!) == .orderedDescending}

As you can see, I'm force unwrapping the date. I'm looking for another way so that if the date is nil, the object moves to the end of array.

2 Answers

Here's an example of how to sort the nil dates to the end of an array.

In the example, movies is an array of type Movie, which has a date property.

let sortedMovies = movies.sorted { (movieA, movieB) -> Bool in

    switch (movieA.date, movieB.date) {
    case (.some, .some):
        return movieA.date! > movieB.date!

    case (.some, .none):
        return true

    case (.none, _):
        return false
    }
}

Here are some extensions for this function, one non-mutating and one mutating, and with a parameter for descending/ascending.

extension Array
{
    func propertySorted<T: Comparable>(_ property: (Element) -> T?, descending: Bool) -> [Element]
    {
        sorted(by: {
            switch (property($0), property($1)) {
            case (.some, .some):
                return descending ? property($0)! > property($1)! : property($0)! < property($1)!

            case (.some, .none):
                return true

            case (.none, _):
                return false
            }
        })
    }

    mutating func propertySort<T: Comparable>(_ property: (Element) -> T?, descending: Bool)
    {
        sort(by: {
            switch (property($0), property($1)) {
            case (.some, .some):
                return descending ? property($0)! > property($1)! : property($0)! < property($1)!

            case (.some, .none):
                return true

            case (.none, _):
                return false
            }
       })
    }
}

Usage:

let movieNames = movies.propertySorted({ $0.name }, descending: false)
let movieDates = movies.propertySorted({ $0.date }, descending: true)

movies.propertySort({ $0.name }, descending: false)
movies.propertySort({ $0.date }, descending: true)

Extension assistance credit to @Sweeper for answer on Generic function to sort array of class by properties

Related