Trier les éléments du carnet

Souvenez-vous, nous avons choisi d'utiliser un tableau pour contenir les différentes personnes de notre carnet d'adresses, parce que nous avions décidé au début qu'il devrait être possible de trier ces personnes, selon des critères quelconques.

Il est maintenant temps de trier les éléments de notre carnet.

Nous avons déjà utilisé Array#sort pour trier des tableaux contenant des nombres entiers, et des chaînes de caractères. Mais comment pouvons-nous trier des tableaux contenant des structures de données plus complexes (comme nos hachages)?

Lorsque le comportement par défaut n'est pas ce que vous désirez, Array#sort vous permet de spécifier comment trier le tableau. Commençons avec un exemple beaucoup plus facile que notre carnet d'adresses actuel:

amis = [
    [ "Nicolas",  "Rocher"    ],
    [ "François", "Willemart" ],
    [ "Marina",   "Nantini"   ]
]

Nous savons que par défaut la méthode Array#sort appelée sur l'objet amis effectuera le tri en fonction du premier élément de chaque sous-tableau - dans ce cas, les prénoms. Et si nous voulions trier ces éléments par leur noms de famille?

À l'instar des itérateurs, la méthode Array#sort peut accepter un bloc de code. Comme ceci:

amis.sort do |a, b|
    # ...
end

La méthode Array#sort attend 3 comportements de ce bloc de code:

Grâce a cette information, la méthode Array#sort peut savoir exactement comment il faut trier le tableau.

Comment faire pour retourner une valeur? La valeur de retour est tout simplement la valeur de la dernière expression interprétée. Jetons un petit coup d'oeil dans IRB:

Les lignes =>sont les valeurs de retour des expressions.

Trier étant une opération fort courante, il existe donc un opérateur spécialement dédié à ça. L'opérateur <=> retourne pour nous les fameuses valeurs -1, 0 et 1. Essayez ceci dans IRB:

Retournons à notre petit tableau:

amis = [
    [ "Nicolas",  "Rocher"    ],
    [ "François", "Willemart" ],
    [ "Marina",   "Nantini"   ]
]

Et à notre instruction de triage:

amis.sort do |a, b|
    # ...
end

a et b sont des éléments du tableau amis. Le comportement par défaut de Array#sort est équivalent à:

amis.sort do |a, b|
    a[0] <=> b[0]   # Tri sur le premier élément
end

Mais comme nous voulons trier sur le second élément (c'est à dire le nom de famille), nous devons écrire:

amis = amis.sort do |a, b|
    a[1] <=> b[1]   # Tri sur le second élément
end
# Maintenant, les éléments du tableau 'amis' sont triés sur le nom de famille. 

Maintenant que nous connaissons Array#sort un peu mieux, nous sommes prêts à personnaliser le tri du carnet d'adresses. Nous avons:

carnet.sort do |personne_a, personne_b|
    # ...
end

personne_a et personne_b sont tous deux des objets provenant du même hachage. Nous pouvons donc, par exemple, les trier par ordre alphabétique sur leur prénom, en écrivant tout simplement ceci:

carnet.sort do |personne_a, personne_b|
    personne_a["prénom"] <=> personne_b["prénom"]
end

Essayez, ça fonctionne!