Sort Array Of Objects

After creating random value it’s time to keep data in some specified and predictable way.

Let’s say there is an array of Ints. You can use .sorted() on it, Swift knows how to sort it.

let number: [Int] = [2, 4, 5, 3, 5, 11, 23, 404, 301, 400, -1].sorted()

Print it.

number.forEach({print(\($0))})

Output

-1
2
3
4
5
5
11
23
301
400
404

However, Swift doesn’t know how to sort an array of objects.

Let’s say you have a struct of Book.

struct Book {
    let title: String
    let author: String
    let pages: Int
}

And array with few books.

let books: [Book] = [
    
Book(title: “The Art Of War”, author: “Sun Tzu”, pages: 68),
    
Book(title: “The Lord of the Rings”, author: “J.R.R. Tolkien”, pages: 1216),
    
Book(title: “Cycle of Hatred”, author: “Keith R. A. DeCandido”, pages: 272),
    
Book(title: “Blood of Elves”, author: “Andrzej Sapkowski”, pages: 324),
]

You want to sort them alphabetically by title.

.sorted() isn’t available because as I mentioned before Swift doesn’t know how to sort it.

The first option is to use closure inside a sorted method.

let books: [Book] = [
    
Book(title: “The Art Of War”, author: “Sun Tzu”, pages: 68),
    
Book(title: “The Lord of the Rings”, author: “J.R.R. Tolkien”, pages: 1216),
    
Book(title: “Cycle of Hatred”, author: “Keith R. A. DeCandido”, pages: 272),
    
Book(title: “Blood of Elves”, author: “Andrzej Sapkowski”, pages: 324),
].sorted {
    $0.
title < $1.title
}

It works but you have to add this closure everywhere you create such array.

Instead of closure inside the sorted method, you can add a Comparable protocol to Book struct and specify how it should be sorted. The Comparable protocol requires only one method and it’s static func < which returns how to compare object.

struct Book: Comparable {
    
let title: String
    
let author: String
    
let pages: Int

   
 static func < (lhs: Book, rhs: Book) -> Bool {
        lhs.
title < rhs.title
    }
}

Now you can use .sorted() on an array of books without closure inside. Now, sorting logic is in one place and always works in the same way. You can choose what you prefer.

let books: [Book] = [
    
Book(title: “The Art Of War”, author: “Sun Tzu”, pages: 68),
    
Book(title: “The Lord of the Rings”, author: “J.R.R. Tolkien”, pages: 1216),
    
Book(title: “Cycle of Hatred”, author: “Keith R. A. DeCandido”, pages: 272),
    
Book(title: “Blood of Elves”, author: “Andrzej Sapkowski”, pages: 324),
].
sorted()

books.forEach({print(“Book title: \($0.title))})

Output

Book title: Blood of Elves
Book title: Cycle of Hatred
Book title: The Art Of War
Book title: The Lord of the Rings