Comment trier un vecteur en Rust : du débutant au pro
Imaginez : vous écrivez un programme en Rust qui collecte une liste d'utilisateurs — noms, âge, classement. Les données arrivent dans un ordre chaotique. Vous devez les afficher par ordre alphabétique ou, disons, les trier par âge. Une tâche familière ? Si vous avez jeté un œil sur Stack Overflow, vous avez sûrement vu la question « How to sort a vector in Rust? » — elle a recueilli des milliers de vues. Et ce n'est pas un hasard.
Le tri en Rust est l'un de ces sujets où « appeler simplement sort() » peut ne pas fonctionner si vous ne connaissez pas quelques subtilités. Dans cet article, nous allons passer en revue toutes les méthodes populaires pour trier un vecteur : de la méthode de base sort() aux comparateurs personnalisés et au choix entre tri stable et instable. Vous apprendrez comment trier un vecteur en Rust correctement, rapidement et sans panique.
Méthode de base : sort() — quand tout est simple
La façon la plus simple de trier un vecteur est d'utiliser la méthode sort(). Elle fonctionne pour les types qui implémentent le trait Ord — ce qui inclut tous les primitifs standards (nombres, chaînes, caractères).
fn main() { let mut numbers = vec![4, 2, 9, 1, 5, 6]; numbers.sort(); println!("{:?}", numbers); // Sortie : [1, 2, 4, 5, 6, 9]}Notez que la variable numbers est déclarée comme mut (mutable). La méthode sort() modifie le vecteur sur place, donc sans mut, le code ne compilera pas. C'est une erreur typique des débutants — oublier la mutabilité.
La même chose fonctionne pour les chaînes :
fn main() { let mut fruits = vec!["banana", "apple", "cherry", "date"]; fruits.sort(); println!("{:?}", fruits); // Sortie : ["apple", "banana", "cherry", "date"]}Le tri des chaînes par défaut est lexicographique (par ordre alphabétique). Si vous avez besoin d'un tri par longueur ou en ignorant la casse, lisez la section sur les comparateurs personnalisés.
sort_unstable() : quand la vitesse prime sur l'ordre
En Rust, il existe deux variantes de tri : sort() (stable) et sort_unstable() (instable). La différence est que le tri stable conserve l'ordre relatif des éléments égaux, tandis que le tri instable ne le fait pas. Cela semble académique, mais en pratique, c'est important si vous triez des structures complexes et souhaitez conserver l'ordre d'insertion pour des clés égales.
Cependant, sort_unstable() a un avantage : elle est plus rapide et utilise moins de mémoire. Pour les grands vecteurs (des millions d'éléments), la différence peut être significative.
fn main() { let mut scores = vec![85, 92, 85, 70, 92, 60]; scores.sort_unstable(); println!("{:?}", scores); // Sortie : [60, 70, 85, 85, 92, 92] // L'ordre des deux 85 et des deux 92 peut différer de l'original}Quand choisir sort_unstable ? Si l'ordre des éléments égaux ne vous importe pas et que vous recherchez la performance. Si la prévisibilité est importante (par exemple, le tri d'un tableau avec plusieurs colonnes), utilisez sort().
sort_by() : comparateurs personnalisés
Que faire si vous devez trier un vecteur selon une règle non standard ? Par exemple, des nombres par ordre décroissant, des chaînes par longueur, ou des structures personnalisées selon l'un de leurs champs. Pour cela, il existe la méthode sort_by(), qui prend une fermeture de comparaison.
Le comparateur doit retourner un Ordering — l'un des variants : Less, Equal ou Greater. La façon la plus simple d'obtenir un tel résultat est d'utiliser les méthodes .cmp() ou .partial_cmp().
Exemple : tri des nombres par ordre décroissant.
fn main() { let mut numbers = vec![4, 2, 9, 1, 5]; numbers.sort_by(|a, b| b.cmp(a)); println!("{:?}", numbers); // Sortie : [9, 5, 4, 2, 1]}Notez que nous échangeons a et b —