How to sort an array of string by similarity to specific key

You can define your own similarity sorting method. Note that I have also added a hasPrefix priority over the ones which only contains the keyword which you can just remove if you don't want it:

var theArray = ["chill", "nifty", "precooled", "cooldaddy", "cool", "coolguy", "dandy", "uncool"]
let key = "cool"

let sorted = theArray.sorted {
    if $0 == key && $1 != key {
        return true
    }
    else if $0.hasPrefix(key) && !$1.hasPrefix(key)  {
        return true
    }
    else if !$0.hasPrefix(key) && $1.hasPrefix(key)  {
        return false
    }
    else if $0.hasPrefix(key) && $1.hasPrefix(key)
        && $0.count < $1.count  {
        return true
    }
    else if $0.contains(key) && !$1.contains(key) {
        return true
    }
    else if !$0.contains(key) && $1.contains(key) {
        return false
    }
    else if $0.contains(key) && $1.contains(key)
        && $0.count < $1.count {
        return true
    }
    return false
}

print(sorted)   // ["cool", "coolguy", "cooldaddy", "uncool", "precooled", "chill", "nifty", "dandy"]

You can also extend Sequence and create a sorted by key similarity method:

extension Sequence where Element: StringProtocol {
    func sorted<S>(by key: S) -> [Element] where S: StringProtocol {
        sorted {
            if $0 == key && $1 != key {
                return true
            }
            else if $0.hasPrefix(key) && !$1.hasPrefix(key)  {
                return true
            }
            else if !$0.hasPrefix(key) && $1.hasPrefix(key)  {
                return false
            }
            else if $0.hasPrefix(key) && $1.hasPrefix(key)
                && $0.count < $1.count  {
                return true
            }
            else if $0.contains(key) && !$1.contains(key) {
                return true
            }
            else if !$0.contains(key) && $1.contains(key) {
                return false
            }
            else if $0.contains(key) && $1.contains(key)
                && $0.count < $1.count {
                return true
            }
            return false
        }
    }
}

let sorted = theArray.sorted(by: key)  // "cool", "coolguy", "cooldaddy", "uncool", "precooled", "chill", "nifty", "dandy"]

And the mutating version as well:

extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
    mutating func sort<S>(by key: S) where S: StringProtocol {
        sort {
            if $0 == key && $1 != key {
                return true
            }
            else if $0.hasPrefix(key) && !$1.hasPrefix(key)  {
                return true
            }
            else if !$0.hasPrefix(key) && $1.hasPrefix(key)  {
                return false
            }
            else if $0.hasPrefix(key) && $1.hasPrefix(key)
                && $0.count < $1.count  {
                return true
            }
            else if $0.contains(key) && !$1.contains(key) {
                return true
            }
            else if !$0.contains(key) && $1.contains(key) {
                return false
            }
            else if $0.contains(key) && $1.contains(key)
                && $0.count < $1.count {
                return true
            }
            return false
        }
    }
}


First you need a measure of how similar two strings are. Here's a simple example:

extension String {
    func equalityScore(with string: String) -> Double {
        if self == string {
            return 2     // the greatest equality score this method can give
        } else if self.contains(string) {
            return 1 + 1 / Double(self.count - string.count)   // contains our term, so the score will be between 1 and 2, depending on number of letters.
        } else {
            // you could of course have other criteria, like string.contains(self)
            return 1 / Double(abs(self.count - string.count))
        }
    }
}

Once you have that, you can use it to sort the array:

var theArray: [String] = ["uncool", "chill", "nifty", "precooled", "dandy", "cool"]

var compareString = "cool"

theArray.sort { lhs, rhs in
    return lhs.equalityScore(with: compareString) > rhs.equalityScore(with: compareString)
}

Result: ["cool", "uncool", "precooled", "chill", "nifty", "dandy"]