Contactez-nous

Ensembles (sets) : collections non ordonnées d'éléments uniques

Découvrez les ensembles (sets) en Python, des collections non ordonnées d'éléments uniques. Apprenez à les créer, les manipuler, et à utiliser leurs opérations ensemblistes (union, intersection, différence).

Qu'est-ce qu'un ensemble (set) en Python ? Définition et caractéristiques

En Python, un ensemble (set) est une structure de données qui permet de stocker une collection non ordonnée d'éléments uniques. Cela signifie que :

  • Non ordonné : Les éléments d'un ensemble ne sont pas stockés dans un ordre particulier. Vous ne pouvez pas accéder aux éléments par leur position (comme dans les listes ou les tuples).
  • Eléments uniques : Un ensemble ne peut pas contenir de doublons. Si vous essayez d'ajouter un élément déjà présent dans l'ensemble, il ne sera pas ajouté à nouveau.
  • Modifiable (mutable) : Vous pouvez ajouter et supprimer des éléments d'un ensemble après sa création (contrairement aux tuples).
  • Eléments immuables : Les éléments d'un ensemble doivent être immuables (comme des nombres, des chaînes de caractères, ou des tuples). Vous ne pouvez pas stocker des listes ou des dictionnaires dans un ensemble.
  • Hétérogène Les éléments peuvent être de différents types.

Les ensembles sont particulièrement utiles pour effectuer des opérations ensemblistes (comme l'union, l'intersection, la différence) et pour tester l'appartenance d'un élément à un ensemble de manière efficace.

Créer un ensemble : différentes méthodes

Il existe plusieurs façons de créer un ensemble en Python :

  • Utiliser des accolades `{}` : C'est la méthode la plus courante. Vous pouvez créer un ensemble vide (attention : `{}` crée un dictionnaire vide, pas un ensemble vide !) ou un ensemble contenant des éléments initiaux. Séparez les éléments par des virgules.
  • Utiliser la fonction `set()` : Vous pouvez convertir un itérable (comme une liste, un tuple, ou une chaîne de caractères) en ensemble. Cela supprimera automatiquement les doublons.
  • Utiliser une compréhension d'ensemble (set comprehension) : Similaire aux compréhensions de listes et de dictionnaires, mais pour créer des ensembles.

Exemples :

# Ensemble vide
ensemble_vide = set()  # {} créerait un dictionnaire vide

# Ensemble avec des éléments initiaux
nombres = {1, 2, 3, 4, 5}
couleurs = {"rouge", "vert", "bleu"}

# Ensemble à partir d'une liste (suppression des doublons)
ma_liste = [1, 2, 2, 3, 3, 3, 4]
mon_ensemble = set(ma_liste)  # {1, 2, 3, 4}

# Ensemble à partir d'une chaîne de caractères
lettres = set("Bonjour")  # {'B', 'r', 'u', 'j', 'o', 'n'} (l'ordre n'est pas garanti)

# Ensemble créé avec une compréhension d'ensemble
pairs = {x for x in range(10) if x % 2 == 0}  # {0, 2, 4, 6, 8}

Ajouter et supprimer des éléments d'un ensemble

Vous pouvez ajouter un élément à un ensemble en utilisant la méthode `add()` :

nombres = {1, 2, 3}
nombres.add(4)  # {1, 2, 3, 4}
nombres.add(3)  # {1, 2, 3, 4} (l'élément 3 est déjà présent, il n'est pas ajouté à nouveau)

Pour ajouter plusieurs éléments d'un coup, vous pouvez utiliser la méthode `update()` avec un itérable en argument :

nombres = {1, 2, 3}
nombres.update([3, 4, 5]) # {1, 2, 3, 4, 5}

Pour supprimer un élément d'un ensemble, vous pouvez utiliser la méthode `remove()` ou la méthode `discard()` :

nombres = {1, 2, 3, 4, 5}

nombres.remove(3)  # {1, 2, 4, 5}
# nombres.remove(6)  # Lèverait une KeyError car 6 n'est pas dans l'ensemble

nombres.discard(4)  # {1, 2, 5}
nombres.discard(6)  # Ne fait rien (pas d'erreur) car 6 n'est pas dans l'ensemble

La différence entre `remove()` et `discard()` est que `remove()` lève une erreur `KeyError` si l'élément n'est pas présent dans l'ensemble, tandis que `discard()` ne fait rien dans ce cas.

Vous pouvez aussi utiliser la méthode `pop()` pour supprimer et retourner un élément arbitraire de l'ensemble. Cependant, comme les ensembles ne sont pas ordonnés, vous ne savez pas quel élément sera supprimé.

mon_ensemble = {1, 2, 3}
element = mon_ensemble.pop() # Supprime et retourne un élément arbitraire

Pour supprimer tous les éléments d'un ensemble, vous pouvez utiliser la méthode `clear()` :

mon_ensemble = {1, 2, 3}
mon_ensemble.clear()
print(mon_ensemble) # set()

Opérations ensemblistes : union, intersection, différence, etc.

L'un des principaux intérêts des ensembles est qu'ils permettent d'effectuer des opérations ensemblistes de manière efficace.

Voici les opérations ensemblistes les plus courantes :

  • Union (`|` ou `union()`) : Retourne un nouvel ensemble contenant tous les éléments présents dans l'un ou l'autre des ensembles (ou les deux).
  • Intersection (`&` ou `intersection()`) : Retourne un nouvel ensemble contenant tous les éléments présents dans les deux ensembles.
  • Différence (`-` ou `difference()`) : Retourne un nouvel ensemble contenant tous les éléments présents dans le premier ensemble mais pas dans le second.
  • Différence symétrique (`^` ou `symmetric_difference()`) : Retourne un nouvel ensemble contenant tous les éléments présents dans l'un ou l'autre des ensembles, mais pas dans les deux.
  • Sous-ensemble (`<=` ou `issubset()`) : Teste si tous les éléments d'un ensemble sont présents dans un autre ensemble.
  • Sur-ensemble (`>=` ou `issuperset()`) : Teste si tous les éléments d'un autre ensemble sont présents dans l'ensemble courant.
  • Disjoints (`isdisjoint()`) Teste si deux ensembles n'ont aucun élément en commun.

Exemples :

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

# Union
print(a | b)  # {1, 2, 3, 4, 5, 6} (ou a.union(b))

# Intersection
print(a & b)  # {3, 4} (ou a.intersection(b))

# Différence
print(a - b)  # {1, 2} (ou a.difference(b))
print(b - a)  # {5, 6} (ou b.difference(a))

# Différence symétrique
print(a ^ b)  # {1, 2, 5, 6} (ou a.symmetric_difference(b))

# Sous-ensemble
c = {1, 2}
print(c <= a)  # True (ou c.issubset(a))
print(a <= c) # False

# Sur-ensemble
print(a >= c) # True (ou a.issuperset(c))

# Disjoints
d = {7, 8}
print(a.isdisjoint(b)) # False
print(a.isdisjoint(d)) # True

Compréhensions d'ensembles : création concise

Comme pour les listes et les dictionnaires, il existe une syntaxe concise pour créer des ensembles, appelée "compréhension d'ensemble".

La syntaxe est la suivante :

{expression for item in iterable if condition}
  • `expression` : Une expression qui est évaluée pour chaque `item` de l'`iterable`. Le résultat est ajouté à l'ensemble.
  • `item` : Une variable qui prend successivement la valeur de chaque élément de l'`iterable`.
  • `iterable` : Une séquence (liste, tuple, chaîne de caractères, etc.) ou un itérable.
  • `condition` (optionnelle) : Une condition qui filtre les éléments de l'iterable`.

Exemple : Créer un ensemble des lettres uniques d'un mot (en minuscules) :

mot = "Bonjour"
lettres_uniques = {lettre.lower() for lettre in mot}
print(lettres_uniques)  # {'b', 'r', 'u', 'j', 'o', 'n'} (l'ordre n'est pas garanti)

Exemple avec une condition :

nombres = [1, 2, 3, 4, 5, 6]
pairs = {x for x in nombres if x % 2 == 0}  # {2, 4, 6}

frozenset : ensembles immuables

Python propose un type `frozenset` qui est une version immuable des `sets`. Cela signifie qu'une fois un `frozenset` créé, il n'est plus possible de le modifier.

Les `frozenset` peuvent être utiles dans les contextes suivants :

  • Clés de dictionnaire : Comme les clés de dictionnaires doivent être immuables, il est possible d'utiliser un `frozenset` comme clé, mais pas un `set`.
  • Eléments d'un autre set Comme les éléments d'un set doivent être immuables, il est possible de stocker un `frozenset` dans un `set`, mais pas un autre `set`.

On crée un `frozenset` avec la fonction du même nom :

mon_frozenset = frozenset([1, 2, 3])

Les méthodes qui ne modifient pas le `set` (comme `copy()`, `issubset()`, `union()`...) sont disponibles pour le `frozenset`.