I want to sort an array of strings so that alphabetic characters are always before any other kinds of characters. For example:
[\"800\", \"word\", \"test\"]
The key is to write your "is ordered before" function to do whatever you want. For example, if by digits, you mean "0"..."9", then something like this is probably what you want:
func isDigit(c: Character) -> Bool {
return "0" <= c && c <= "9"
}
func sortedLettersFirst(lhs: String, rhs: String) -> Bool {
for (lc, rc) in zip(lhs.characters, rhs.characters) {
if lc == rc { continue }
if isDigit(lc) && !isDigit(rc) {
return false
}
if !isDigit(lc) && isDigit(rc) {
return true
}
return lc < rc
}
return lhs.characters.count < rhs.characters.count
}
words.sort(sortedLettersFirst)
Of course, if by "digit" you mean "unicode digits", then see What is the replacement for isDigit() for characters in Swift? for a different approach to isDigit
. But ultimately, the point is to make whatever rule you want in your isOrderedBefore
function, and pass that to sort()
.
How about this.
func sortedNumbersLast(words: [String]) -> [String] {
var startsWithDigit = [String]()
var startsWithCharacter = [String]()
for word in words {
if let first = word.characters.first {
if first >= "0" && first <= "9" {
startsWithDigit.append(word)
}
else {
startsWithCharacter.append(word)
}
}
}
return startsWithCharacter.sort(<) + startsWithDigit.sort(<)
}
Try this in Playground, as you can see in the console output it gets the job done, letters are being placed at the front, followed by numbers and other symbols are at the end.
let stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd: (String, String) -> Bool = { s1, s2 -> Bool in
guard let f1 = s1.first, let f2 = s2.first else {
return s1 < s2
}
if f1.isLetter == false && f2.isLetter {
return false
}
if f1.isLetter && f2.isLetter == false {
return true
}
if f1.isNumber == false && f2.isNumber {
return false
}
if f1.isNumber && f2.isNumber == false {
return true
}
return s1 < s2
}
let str = ["4", "A", "B", "Z", "T", "3", "'", "8"]
print(str.sorted(by: stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd))
Above method sorts String in ascending order, if you want to do the other way just change the lines
return s1 < s2
to
return s1 > s2