Aller au contenu

Trier une liste de tuples

Pour présenter une liste, il est souvent utile de la présenter triée. Mais lorsque cette liste est composée de plusieurs champs, on peut trier suivant chacun de ces champs ou suivant des valeurs faisant intervenir plusieurs des champs... Illustration dans les exerices qui suivent.

Trier suivant la première note

On dispose des notes de plusieurs élèves:

cahier_de_notes = [('Adèle', 8, 12, 9), ('Baptiste', 2, 18, 15), 
('Cassandre', 14, 13, 17), ('Doris', 10, 11, 12)]
(on peut supposer que la liste ne s'arrête pas là...)

Adèle a pour notes (8, 12, 9), 8 étant la première note obtenue, 12 la seconde...
Baptiste a pour notes (2, 18, 15)...

Ecrire une fonction permettant de trier une telle liste suivant l'ordre croissant des premières notes obtenues.

Solution

On peut écrire:

    def première_note(uple):
        """
        uple  est un tuple (nom, note 1, note 2, note 3)
        renvoie la première note 
        """
        return uple[1]



    def tri_suivant_note1(tab):
    """
    tab: un "cahier_de_notes"
    trie le cahier de notes suivant la première note
    """
    tab.sort(key=première_note)

Utilisation:

>>> cahier_de_notes = [('Adèle', 8, 12, 9), ('Baptiste', 2, 18, 15), ('Cassandre', 14, 13, 17), 
('Doris', 10, 11, 12)]
>>> tri_suivant_note1(cahier_de_notes)
>>> cahier_de_notes
[('Baptiste', 2, 18, 15), ('Adèle', 8, 12, 9), ('Doris', 10, 11, 12), ('Cassandre', 14, 13, 17)]
Fonction lambda

Python permet une syntaxe plus brève, évitant la définition de la fonction intermédiaire:

>>> cahier_de_notes = [('Adèle', 8, 12, 9), ('Baptiste', 2, 18, 15), ('Cassandre', 14, 13, 17), 
    ('Doris', 10, 11, 12)]
>>> cahier_de_notes.sort(key = lambda x: x[1])
>>> cahier_de_notes
[('Baptiste', 2, 18, 15), ('Adèle', 8, 12, 9), ('Doris', 10, 11, 12), ('Cassandre', 14, 13, 17)]

Vous pouvez faire une recherche sur le web sur les fonctions lambda du langage Python pour en savoir plus.

Tri suivant la dernière note obtenue

Trier une liste cahier_de_notes suivant le résultat obtenu par les élèves lors du dernier contrôle (en ordre croissant).

Solution
def dernière_note(uple):
    """
    uple  est un tuple (nom, note 1, note 2, note 3)
    renvoie la dernière note 
    """
    return uple[-1]



def tri_suivant_dernière_note(tab):
    """
    tab: un "cahier_de_notes"
    trie le cahier de notes suivant la dernière note
    """
    tab.sort(key=dernière_note)

Utilisation:

>>> cahier_de_notes = [('Adèle', 8, 12, 9), ('Baptiste', 2, 18, 15), ('Cassandre', 14, 13, 17), 
('Doris', 10, 11, 12)]
>>> tri_suivant_dernière_note(cahier_de_notes)
>>> cahier_de_notes
[('Adèle', 8, 12, 9), ('Doris', 10, 11, 12), ('Baptiste', 2, 18, 15), ('Cassandre', 14, 13, 17)]

Tri suivant la moyenne

Trier une liste cahier_de_notes en ordre décroissant des moyennes arithmétiques des élèves sur l'ensemble des contrôles.

Solution
def moyenne(resultats_eleve):
    """
    resultats_eleve  est un tuple (nom, note 1, note 2, note 3)
    renvoie la moyenne des notes
    """
    somme = 0
    for i, note in enumerate(resultats_eleve):
        if i == 0:
            pass # on passe le nom
        else:
            somme += note 
    nombre_notes = len(resultats_eleve)-1 
    return somme/nombre_notes



def tri_suivant_moyenne(tab):
    """
    tab: un "cahier_de_notes"
    trie le cahier de notes suivant la moyenne des notes
    """
    tab.sort(key=moyenne, reverse=True)    

Utilisation:

>>> cahier_de_notes = [('Adèle', 8, 12, 9), ('Baptiste', 2, 18, 15), ('Cassandre', 14, 13, 17), 
('Doris', 10, 11, 12)]
>>> tri_suivant_moyenne(cahier_de_notes)
>>> cahier_de_notes
[('Cassandre', 14, 13, 17), ('Baptiste', 2, 18, 15), ('Doris', 10, 11, 12), ('Adèle', 8, 12, 9)]

Tri suivant l'amplitude

Trier le cahier de notes en ordre croissant suivant l'amplitude des notes de l'élève sur les trois contrôles.

Définition

L'amplitude pour les notes d'un élève est l'écart entre la plus grande note de l'élève et sa plus petite note.

Aide

On pourra, pour simplifier, utiliser les fonctions python max et min.

Solution
def amplitude(resultats_eleve):
    """
    resultats_eleve  est un tuple (nom, note 1, note 2, note 3)
    renvoie l'amplitude des notes
    """
    notes = [note for i, note in enumerate(resultats_eleve) if i != 0]
    return max(notes) - min(notes)



def tri_suivant_amplitude(tab):
    """
    tab: un "cahier_de_notes"
    trie le cahier de notes suivant l'amplitude
    """
    tab.sort(key=amplitude)

Tri mystère (exercice facultatif)

Quel pourrait être l'effet du code suivant sur une liste L (contenant par exemple des entiers ou contenant des chaînes de caractères):

>>> from random import randint
>>> t = len(L)
>>> L.sort(key= lambda x: randint(1, t))
Solution

Vous pouvez tester par exemple avec une liste de chaînes:

>>> from random import randint
>>> L = ["aha", "oh", "aïe", "zut", "zou", "charivari", "shadock"]
>>> t = len(L)
>>> L.sort(key= lambda x: randint(1, t))
>>> L

On associe un entier au hasard à chaque élément de la liste et on trie suivant l'ordre croissant de ces entiers. Cela revient à mélanger la liste.

Note

Pour mélanger une liste, le module random offre la fonction shuffle.