Menu
Coddy logo textTech

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 icon

Challenge

Medium

Read a single line of input: a comma-separated list of name:age pairs.

Print three lines:

  1. Names sorted by age ascending, joined with ,. Break ties by sorting the tied names alphabetically.
  2. The name of the oldest person (use max(by:)). On a tie, the one that appears first wins.
  3. 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
dan

Cheat 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
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Logic & Flow