Kashif
Kashif

Reputation: 4632

Custom Sort Order with Predicates

I have an array

arr = ["A", "B", "a", "b", "1", "2"]

When I sort it using:

arr.sorted(by: <)

I get:

["1", "2", "A", "B", "a", "b"]

But I am looking for the result:

["a", "b", "A", "B", "1", 2"]

Sort of a custom sort order where smalls come first in sorted order then caps in sorted order and then numbers in sorted order. What is an easy way to do it?

Upvotes: 0

Views: 255

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236448

I might be wrong but I think you will need to implement your own custom sorting method:

var arr = ["A", "B", "a", "b", "1", "2"]
arr.sort {
    if $0.first?.isLowercase == true && ($1.first?.isUppercase == true || $1.first?.isWholeNumber == true) {
        return true
    }
    if $0.first?.isUppercase == true && $1.first?.isWholeNumber == true {
        return true
    }
    if $0.first?.isWholeNumber == true && ($1.first?.isLowercase == true ||  $1.first?.isUppercase == true) {
        return false
    }
    return $0 < $1
}

print(arr) // "["a", "b", "A", "B", "1", "2"]\n"

extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
    mutating func customSort(by areInIncreasingOrder: (Element, Element) throws -> Bool = (<)) rethrows {
        try sort {
            if try areInIncreasingOrder("1","2") {
                if $0.first?.isLowercase == true && ($1.first?.isUppercase == true || $1.first?.isWholeNumber == true) {
                    return true
                }
                if $0.first?.isUppercase == true && $1.first?.isWholeNumber == true {
                    return true
                }
                if $0.first?.isWholeNumber == true && ($1.first?.isLowercase == true ||  $1.first?.isUppercase == true) {
                    return false
                }
            } else {
                if $0.first?.isWholeNumber == true && ($1.first?.isLowercase == true ||  $1.first?.isUppercase == true) {
                    return true
                }
                if $0.first?.isUppercase == true && ($1.first?.isLowercase == true || $1.first?.isWholeNumber == true) {
                    return true
                }
                if $0.first?.isLowercase == true && ($1.first?.isUppercase == true || $1.first?.isWholeNumber == true) {
                    return false
                }
            }
            return try areInIncreasingOrder($0,$1)
        }
    }
}

var array =  ["B","A","b", "a", "1", "2"]
do {
    try array.customSort()
    print(array) // "["a", "b", "A", "B", "1", "2"]\n"
} catch {
    print(error)
}

Upvotes: 2

Related Questions