Aller au contenu

Les tuples et les ensembles

Objectifs de la section

2-3 Manipulation de tableaux et dictionnaires de données

Temps requis

40 minutes

Les listes proposent une structure de donnée flexible et simple que l'on peut utiliser dans toutes les circonstances ou presque. Après tout, les premiers langages de programmation ne proposaient que la structure de liste. Il arrive cependant que les besoins en stockage de données soient différents et que l'on puisse utiliser une collection de données spécialisée. Dans cette section, deux collections de données sont présentées : les tuples et les ensembles.

Les tuples de données

Section 9.1

Les tuples de données sont une structure de donnée immuable : on ne peut pas en modifier les éléments après la déclaration. Cependant, chaque élément est accessible avec le système d'indice. Un cas d'utilisation très fréquent des tuples est la représentation de vecteurs mathématiques.

Pour définir un tuple, on place entre parenthèses ( ) les valeurs que l'on sépare par des virgules.

Définition d'un tuple
vecteur = (2, 5)

On peut ensuite accéder aux éléments avec le système d'indices. L'utilisation d'indice négatif et le parcours du tuple sont similaires à celui de la liste.

Manipulation d'un tuple
vecteur = (2, 5)

print(vecteur[0])       # Affiche 2
print(vecteur[-1])      # Affiche 5

# Affiche chaque valeur du tuple
for x in vecteur:
    print(x)

vecteur[1] = 3          # TypeError: 'tuple' object does not support item assignment

L'égalité entre deux tuples est la même que celle entre deux listes : tous les éléments aux mêmes positions sont égaux.

Comparaison entre structures

Si deux structures différents (comme une liste et un tuple) contiennent les mêmes éléments aux mêmes positions, elles seront quand même identifiées comme différente

Comparaison d'une liste et d'un tule
1
2
3
4
5
liste = [1, 2, 3]
# tuple est un mot réservé.
tuple_donnees = (1, 2, 3)

print(liste == tuple_donnees)   # Affiche False

Créer un tuple avec un élément

Comparons les deux codes suivants :

Ambiguïté de la création de tuple à un élément
tuple_un_element = (3)
chiffre_trois_avec_parentheses = (3)

On remarque que dans les deux cas, on exécute le même code qui retourne la même valeur, soit le nombre 3 et non pas un tuple qui contient le nombre 3. Pour indiquer que l'on veut créer un tuple, on ajoute une virgule après le dernier élément.

Lever l'ambiguïté de la création de tuple à un élément
tuple_un_element = (3, )
chiffre_trois_avec_parentheses = (3)

La virgule à la fin

En python, il est valide de terminer l'initialisation d'un conteneur de données par une virgule, y compris les conteneurs de liste, d'ensemble et de dictionnaire.

Les ensembles

Section 9.6

Un ensemble est une collection de données qui ne supporte pas les valeurs répétées. On se sert des ensembles dans deux cas :

  • Représentation d'un ensemble mathématique (théorie des ensembles ou des probabilités);
  • Liste de variable ou d'identifiants uniques.

Pour définir un ensemble, on place entre accolades { } les valeurs que l'on sépare par des virgules. Sur plusieurs claviers, elles sont accessibles avec les touches Alt Car et celles à côté du point-virgule.

Définition d'un ensemble
1
2
3
4
5
ensemble = {"A", "B", "C"}
print(ensemble)     # Affiche {'A', 'C', 'B'}

ensemble2 = {"A", "C", "B", "B"}
print(ensemble2)    # Affiche  {'A', 'C', 'B'}

On remarque de ce premier exemple que les éléments répétés à l'initialisation sont éliminés de l'ensemble et que l'ordre des éléments n'est pas préservé. Pour les ensembles, il n'y a pas de système d'indice, donc on ne peut pas parcourir les éléments dans un ordre séquentiel.

Égalité des ensembles

Deux ensembles qui contiennent les mêmes éléments sont égaux entre eux. On utilise l'opérateur d'égalité == pour faire cette vérification.

Égalité d'ensemble
1
2
3
4
ensemble = {"A", "B", "C"}
ensemble2 = {"A", "C", "B", "B"}

print(ensemble == ensemble2)        # Affiche True

Parcourir les éléments

Pour parcourir les éléments d'un ensemble, on utilise la boucle for avec le parcours par valeur. Il n'y a pas de garantie que les éléments sont toujours parcourus dans le même ordre. Si vous exécutez le code ci-dessous plusieurs fois, l'affichage ne sera pas toujours le même. Évidemment, le parcours par indice ne fonctionne pas.

Parcours d'un ensemble
1
2
3
4
ensemble = {"A", "B", "C"}

for element in ensemble:
    print(element)

Opérateur d'appartenance

L'opérateur d'appartenance in peut être utilisé comme pour les listes afin de vérifier si un élément est dans un ensemble.

Les fonctions sur les ensembles

Plusieurs fonctions permettent de manipuler les ensembles. Certains sont similaires à celles des collections de données et d'autres proviennent des opérations mathématiques sur les ensembles.

Ajouter des éléments

On peut ajouter un élément à un ensemble avec la fonction add. Si l'élément est déjà dans l'ensemble, la fonction n'a pas d'effet.

Retirer des éléments

Dans un ensemble, il y a deux façons de retirer les éléments d'un ensemble :

  • Retirer un élément au hasard avec la fonction pop;
  • Retirer un élément spécifique avec la fonction remove. La fonction accepte un élément : l'élément à retirer. Attention, si l'élément n'existe pas dans l'ensemble, une erreur est lancée.
  • Retirer un élément spécifique avec la fonction discard. Elle a le même effet et fonctionnement que remove, mais ne lance pas d'erreur si l'élément à retirer n'est pas dans l'ensemble.

Pourquoi retirer un élément au hasard

Le problème vient du parcours des éléments. Quand on retire un élément dans un ensemble, cela peut changer l'ordre des éléments de l'ensemble. Donc le parcours avec la boucle for n'est pas possible. En fait, le code suivant pose problème :

Erreur de modification durant une itération
ensemble = {"A", "B", "C"}

for element in ensemble:
    ensemble.remove(element)

# Message d'erreur : RuntimeError: Set changed size during iteration

Par contre, le code suivant permet de faire le même traitement, mais sans frapper l'erreur.

Modification valide d'un ensemble durant une itération
ensemble = {"A", "B", "C"}

while len(ensemble) > 0:
    ensemble.pop()

Exemple de problème avec l'ajout et le retrait d'élément

On a une liste de participants à un projet de recherche. Les noms des personnes inscrites se retrouvent dans un ensemble nommé groupe1. Suite au gain de popularité du projet, on doit séparer les participants en deux groupes. Tant que les deux groupes ne sont pas égaux, on déplace des participants du groupe 1 vers le groupe 2.

Filtrer des ensembles
groupe1 = {"Alice", "Bob", "Clara", "Damien", "Erika", "Félix", "Ginette", "Hughes", "Isabelle", "Luke"}
groupe2 = set()     # Crée un ensemble vide, juste {} ne fonctionne pas pour les ensembles.

# On n'utilise pas l'égalité en cas de nombre impairs de participants
while len(groupe1) > len(groupe2) :   
    deplace = groupe1.pop()
    groupe2.add(deplace)

print(f"Le groupe 1 est composé de {groupe1}.")
print(f"Le groupe 2 est composé de {groupe2}.")

Opération sur les ensembles

Les opérations mathématiques d'ensembles sont toutes définies dans Python au moyen de fonctions sur les ensembles. Toutes les fonctions s'appellent sur un ensemble et acceptent en paramètre un autre ensemble. Elles retournent le résultat de l'opération.

Opérateur d'ensemble Symbole mathématique Fonction python Exemple d'utilisation Effet
Union \(A \cup B\) union a.union(b) Combine les éléments de l'ensemble A et B.
Intersection \(A \cap B\) intersction a.intersection(b) Sélectionne les éléments dans A et B.
Différence \(A - B\) difference a.difference(b) Retourne les éléments qui sont dans A et qui ne sont pas dans B.
Différence symétrique \(A \Delta B\) symmetric_difference a.symmetric_difference(b) Retourne les éléments qui sont dans A ou B, mais pas ceux qui sont dans A et B.
Sous-ensemble \(A \subset B\) issubset a.issubset(b) Retourne vrai si tous les éléments de A sont dans B.
Super-ensemble \(B \subset A\) issuperset a.issuperset(b) Retourne vrai si tous les éléments de B sont dans A.
Disjoint isdisjoint a.isdisjoint(b) Retourne vrai si A et B n'ont pas d'éléments communs.

Utilisation des opérations d'ensemble
pairs = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
carres = {1, 4, 9, 16}

# Les nombres pairs ou carres
print(pairs.union(carres))
# Affiche {1, 2, 4, 6, 8, 9, 10, 12, 14, 16, 18, 20}

# Les nombres pairs et carres
print(pairs.intersection(carres))
# Affiche {16, 4}

# Les nombres pairs, sauf ceux qui sont des carrés
print(pairs.difference(carres))
# Affiche {2, 6, 8, 10, 12, 14, 18, 20}

# Les nombres carrés, sauf ceux qui sont pairs
print(carres.difference(pairs))
# Affiche {1, 9}

# Les nombres pairs ou carres, sauf les nombres pairs et carrées
print(pairs.symmetric_difference(carres))
# Affiche {1, 2, 6, 8, 9, 10, 12, 14, 18, 20}

# Est-ce que tous les carrés sont pairs ?
print(carres.issubset(pairs))
# Affiche False
print(pairs.issuperset(carres))
# Affiche False

# Est-ce qu'il existe des nombres carrés et pairs ?
print(not pairs.isdisjoint(carres))
# Affiche True (on utilise l'opéerateur not pour répondre à la question)

Exemple de problème sur les ensembles

On a listé des animaux selon certaines caractéristiques physiologiques. On s'intéresse maintenant aux animaux qui partagent des traits ou non.

Étude très très TRÈS scientifiques sur les animaux communs
animaux_volant = {"Poule", "Chauve-souris", "Papillon", "Aigle"}
animaux_nageant = {"Truite", "Dauphin", "Baleine"}
mammiferes = {"Chauve-souris", "Chat", "Dauphin"}
insectes = {"Fourmi", "Papillon", "Scarabée"}
tous = animaux_volant.union(animaux_nageant, mammiferes, insectes)

# Insectes qui volent
print(f"Insectes qui volent {animaux_volant.intersection(insectes)}")

# Les animaux qui ne volent pas parmis les répertoriés
print(f"Animaux qui ne volent pas {tous.difference(animaux_volant)}")

# Est-ce que tous les animaux qui nagent sont des mammifères
print(f"Est-ce que tous les animaux qui nagent sont des mammifères ? {animaux_nageant.isdisjoint(mammiferes)}")

Arguments multiples

La ligne 5 de l'exemple précédent montre un union entre plusieurs ensemble de façon simultanée. Pour certaines fonctions, dont l'union et l'intersection il est possible de les faire sur plusieurs ensemble simultanément.

Exercices

Voir document d'exercice sur Teams.