sorted(by:)
Part of the Logic & Flow section of Coddy's Swift journey — lesson 30 of 56.
You've used .sorted() on arrays of Comparable values like numbers or strings. When you want to sort by something else, supply a closure that takes two elements and returns true when the first should come before the second.
let words = ["banana", "hi", "hello"]
let byLength = words.sorted { $0.count < $1.count }
print(byLength) // ["hi", "hello", "banana"]For descending order, swap the comparison:
let down = words.sorted { $0.count > $1.count }
print(down) // ["banana", "hello", "hi"]The closure can compare any derived value, length, last letter, an entry in a hash. Whatever the closure compares decides the sort.
min(by:) and max(by:) work the same way but return a single optional element rather than a sorted copy.
Challenge
MediumRead a single line of input: a comma-separated list of name:age pairs.
Print three lines:
- Names sorted by age ascending, joined with
,. Break ties by sorting the tied names alphabetically. - The name of the oldest person (use
max(by:)). On a tie, the one that appears first wins. - The name of the youngest person (use
min(by:)). On a tie, the one that appears first wins.
For input alice:30,bob:22,cara:30,dan:18, the output is:
dan,bob,alice,cara
alice
danCheat sheet
Use .sorted { } with a custom closure to sort by any derived value. The closure takes two elements and returns true when the first should come before the second:
let words = ["banana", "hi", "hello"]
let byLength = words.sorted { $0.count < $1.count }
// ["hi", "hello", "banana"]For descending order, swap the operator:
let down = words.sorted { $0.count > $1.count }
// ["banana", "hello", "hi"]min(by:) and max(by:) use the same closure signature but return a single optional element:
let longest = words.max(by: { $0.count < $1.count }) // "banana"
let shortest = words.min(by: { $0.count < $1.count }) // "hi"Try it yourself
let people = readLine()!.components(separatedBy: ",").map { pair -> (String, Int) in
let parts = pair.components(separatedBy: ":")
return (parts[0], Int(parts[1])!)
}
// TODO: sort by age asc (tiebreak by name); max(by:) for oldest; min(by:) for youngest
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
Count and IndicesCase and TrimSearching in StringsSplitting and JoiningReplacing SubstringsRecap - Username Check