Tri de tableaux d'objets en Swift : du simple au complexe

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Comment trier un tableau d'objets par propriété en Swift : regardons sous le capot



Bonjour, collègue ! Si tu as déjà écrit une application en Swift qui affiche une liste d'utilisateurs, de produits ou de tâches, tu as sûrement eu besoin de trier ces données. La question « How to sort an array of custom objects by property value? » est l'une des plus populaires sur Stack Overflow. Et ce n'est pas sans raison : à première vue, tout semble simple, mais dès qu'on creuse un peu, tout un éventail de possibilités s'ouvre.



Aujourd'hui, nous ne nous contenterons pas de donner une réponse toute faite. Nous allons voir comment fonctionne le tri sous le capot de Swift, quels mécanismes sont impliqués et comment écrire un code non seulement fonctionnel, mais efficace et élégant. C'est parti !



Qu'est-ce que le tri d'un tableau d'objets en Swift ?



Imagine : tu as un tableau d'objets User. Chaque utilisateur a un nom, un âge et une note. Tu dois les afficher à l'écran, triés par âge (du plus jeune au plus âgé).



En Swift, cela se fait avec les méthodes intégrées sort() (trie le tableau sur place) et sorted() (retourne un nouveau tableau trié). Les deux acceptent une fermeture qui définit l'ordre.



struct User {    let name: String    let age: Int    let rating: Double}

let users = [ User(name: "Anna", age: 25, rating: 4.5), User(name: "Boris", age: 30, rating: 3.8), User(name: "Vika", age: 22, rating: 4.9)]

// Tri par âge (croissant)let sortedByAge = users.sorted { $0.age < $1.age }print(sortedByAge.map { $0.name }) // ["Vika", "Anna", "Boris"]


Et voilà. Mais voyons ce qui se passe réellement ici.



Comment fonctionne sort() sous le capot : algorithmes et fermetures



La méthode sort() en Swift utilise un algorithme hybride appelé TimSort (nommé d'après Tim Peters). C'est un algorithme de tri adaptatif et stable qui combine le tri par fusion et le tri par insertion. Il est particulièrement efficace sur des données partiellement triées — bonjour les flux d'actualités et les listes de tâches !



La fermeture que tu passes est un prédicat de tri : une fonction qui prend deux éléments et retourne true si le premier doit être placé avant le second. Swift appelle cette fermeture à plusieurs reprises, en comparant des paires d'éléments.



Important : si tes objets sont conformes au protocole Comparable, tu peux même te passer de fermeture :



struct User: Comparable {    let name: String    let age: Int        static func < (lhs: User, rhs: User) -> Bool {        return lhs.age < rhs.age    }}

let sortedUsers = users.sorted() // maintenant c'est simple


Mais que faire si tu dois trier selon différentes propriétés à l'exécution ? C'est là qu'interviennent les chemins clés (KeyPath).



Tri avec KeyPath : élégance et flexibilité



Depuis Swift 4, nous avons KeyPath. C'est un moyen sûr de référencer une propriété d'un objet. En combinant KeyPath avec des fermetures, on peut écrire une fonction de tri universelle :



extension Array {    mutating func sort<T: Comparable>(by keyPath: KeyPath<Element, T>, ascending: Bool = true) {        sort { ascending ?            $0[keyPath: keyPath] < $1[keyPath: keyPath] :            $0[keyPath: keyPath] > $1[keyPath: keyPath]        }    }        func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>, ascending: Bool = true) -> [Element] {        return sorted { ascending ?            $0[keyPath: keyPath] < $1[keyPath: keyPath] :            $0[keyPath: keyPath] > $1[keyPath: keyPath]        }    }}

// Utilisation :users.sort(by: \\.age) // par âge (croissant)let sortedByRating = users.sorted(by: \\.rating, ascending: false) // par note (décroissant)


Magnifique, non ? Sécurité de typage

Blogs

Book Recommendations