Comment convertir une liste Python en un ensemble tout en préservant l'ordre d'origine

PythonPythonBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Les structures de données intégrées de Python offrent des moyens flexibles pour gérer et manipuler les données. Dans ce tutoriel, nous allons explorer comment convertir une liste Python en un ensemble (set) tout en préservant l'ordre original des éléments. Cette technique est particulièrement utile lorsque vous devez supprimer les doublons d'une liste tout en conservant l'ordre de la première occurrence de chaque élément unique.

À la fin de ce tutoriel, vous comprendrez les différences entre les listes et les ensembles en Python et apprendrez plusieurs techniques pour convertir une liste en un ensemble tout en conservant l'ordre original des éléments.

Comprendre les listes et les ensembles en Python

Avant de plonger dans la conversion des listes en ensembles, comprenons les propriétés de base de ces deux structures de données en Python.

Listes Python

Les listes en Python sont des collections ordonnées qui peuvent stocker des éléments de différents types de données. Elles autorisent les valeurs en double et conservent l'ordre d'insertion des éléments.

Créons un simple fichier Python pour illustrer les listes. Ouvrez l'éditeur de code et créez un nouveau fichier nommé list_demo.py dans le répertoire /home/labex/project :

## Listes en Python
my_list = [1, 2, 3, 2, 4, 5, 3]

print("Liste originale:", my_list)
print("Longueur de la liste:", len(my_list))
print("Premier élément:", my_list[0])
print("Dernier élément:", my_list[-1])
print("3 premiers éléments:", my_list[:3])
print("La liste contient-elle des doublons ?", len(my_list) != len(set(my_list)))

Exécutez maintenant ce fichier dans le terminal :

python3 list_demo.py

Vous devriez voir une sortie similaire à celle-ci :

Original list: [1, 2, 3, 2, 4, 5, 3]
Length of list: 7
First element: 1
Last element: 3
First 3 elements: [1, 2, 3]
Does list contain duplicates? True

Ensembles (Sets) Python

Les ensembles sont des collections non ordonnées d'éléments uniques. Lorsque vous convertissez une liste en un ensemble, les éléments en double sont automatiquement supprimés, mais l'ordre original n'est pas conservé.

Créons un autre fichier nommé set_demo.py pour explorer les ensembles :

## Ensembles en Python
my_list = [1, 2, 3, 2, 4, 5, 3]
my_set = set(my_list)

print("Liste originale:", my_list)
print("Converti en ensemble:", my_set)
print("Longueur de la liste:", len(my_list))
print("Longueur de l'ensemble:", len(my_set))
print("L'ensemble conserve-t-il l'ordre ?", list(my_set) == [1, 2, 3, 4, 5])

Exécutez ce fichier :

python3 set_demo.py

La sortie affichera :

Original list: [1, 2, 3, 2, 4, 5, 3]
Converted to set: {1, 2, 3, 4, 5}
Length of list: 7
Length of set: 5
Does set maintain order? False

Notez que l'ensemble a supprimé tous les doublons, mais l'ordre peut être différent de la liste originale. Cela est dû au fait que les ensembles en Python sont intrinsèquement non ordonnés.

Approche de base : Conversion d'une liste en un ensemble

Maintenant que nous comprenons les différences entre les listes et les ensembles, explorons comment convertir une liste en un ensemble et les implications de cette conversion.

Conversion simple

La méthode la plus simple pour convertir une liste en un ensemble consiste à utiliser la fonction intégrée set(). Créez un nouveau fichier nommé basic_conversion.py :

## Conversion de base d'une liste en ensemble
fruits = ["apple", "banana", "orange", "apple", "pear", "banana"]

## Convertir la liste en ensemble (supprime les doublons mais perd l'ordre)
unique_fruits = set(fruits)

print("Liste originale:", fruits)
print("En tant qu'ensemble:", unique_fruits)

## Reconvertir en liste (l'ordre n'est pas conservé)
unique_fruits_list = list(unique_fruits)
print("Retour à la liste:", unique_fruits_list)

Exécutez ce fichier :

python3 basic_conversion.py

Vous devriez voir une sortie similaire à :

Original list: ['apple', 'banana', 'orange', 'apple', 'pear', 'banana']
As a set: {'orange', 'banana', 'apple', 'pear'}
Back to list: ['orange', 'banana', 'apple', 'pear']

Notez que l'ensemble a supprimé tous les doublons, mais l'ordre est différent de la liste originale. Lorsque nous reconvertissons l'ensemble en liste, l'ordre n'est toujours pas le même que notre liste originale.

Le problème avec l'ordre

Cette conversion simple démontre le problème que nous essayons de résoudre : lorsque nous convertissons une liste en un ensemble, nous perdons l'ordre original des éléments. Si l'ordre original est important, cette approche n'est pas adaptée.

Modifions notre exemple pour montrer pourquoi cela pourrait être un problème. Créez un fichier nommé order_matters.py :

## Exemple montrant pourquoi l'ordre est important
steps = ["Preheat oven", "Mix ingredients", "Pour batter", "Bake", "Mix ingredients"]

## Supprimer les doublons en utilisant set
unique_steps = list(set(steps))

print("Étapes de cuisson originales:", steps)
print("Étapes uniques (en utilisant set):", unique_steps)
print("L'ordre est-il conservé ?", unique_steps == ["Preheat oven", "Mix ingredients", "Pour batter", "Bake"])

Exécutez le fichier :

python3 order_matters.py

La sortie sera :

Original cooking steps: ['Preheat oven', 'Mix ingredients', 'Pour batter', 'Bake', 'Mix ingredients']
Unique steps (using set): ['Preheat oven', 'Bake', 'Mix ingredients', 'Pour batter']
Is the order preserved? False

Dans cet exemple, l'ordre des étapes de cuisson est essentiel. Si vous faites cuire avant de mélanger les ingrédients, le résultat sera désastreux. Cela illustre pourquoi nous avons besoin d'un moyen de préserver l'ordre original lors de la suppression des doublons.

Préserver l'ordre lors de la conversion d'une liste en un ensemble

Maintenant que nous comprenons le problème, explorons les méthodes pour convertir une liste en un ensemble tout en préservant l'ordre original des éléments.

Méthode 1 : Utilisation d'un dictionnaire pour préserver l'ordre

Une approche consiste à utiliser un dictionnaire pour suivre l'ordre des éléments. Depuis Python 3.7, les dictionnaires conservent par défaut l'ordre d'insertion.

Créez un nouveau fichier nommé dict_approach.py :

## Utilisation d'un dictionnaire pour préserver l'ordre
fruits = ["apple", "banana", "orange", "apple", "pear", "banana"]

## Créer un dictionnaire avec les éléments de la liste comme clés
## Cela supprime automatiquement les doublons tout en préservant l'ordre
unique_fruits_dict = dict.fromkeys(fruits)

## Convertir les clés du dictionnaire en une liste
unique_fruits = list(unique_fruits_dict)

print("Liste originale:", fruits)
print("Éléments uniques (ordre préservé):", unique_fruits)

Exécutez le fichier :

python3 dict_approach.py

Vous devriez voir :

Original list: ['apple', 'banana', 'orange', 'apple', 'pear', 'banana']
Unique elements (order preserved): ['apple', 'banana', 'orange', 'pear']

Notez que l'ordre de la première occurrence de chaque élément est conservé.

Méthode 2 : Utilisation de OrderedDict

Pour les utilisateurs de versions de Python antérieures à 3.7, ou pour rendre l'intention plus explicite, nous pouvons utiliser OrderedDict du module collections.

Créez un nouveau fichier nommé ordered_dict_approach.py :

## Utilisation de OrderedDict pour préserver l'ordre
from collections import OrderedDict

fruits = ["apple", "banana", "orange", "apple", "pear", "banana"]

## Créer un OrderedDict avec les éléments de la liste comme clés
## Cela supprime automatiquement les doublons tout en préservant l'ordre
unique_fruits_ordered = list(OrderedDict.fromkeys(fruits))

print("Liste originale:", fruits)
print("Éléments uniques (ordre préservé):", unique_fruits_ordered)

Exécutez le fichier :

python3 ordered_dict_approach.py

La sortie devrait être :

Original list: ['apple', 'banana', 'orange', 'apple', 'pear', 'banana']
Unique elements (order preserved): ['apple', 'banana', 'orange', 'pear']

Méthode 3 : Utilisation d'une boucle et d'un ensemble pour la vérification

Une autre approche consiste à utiliser une boucle et un ensemble pour vérifier si nous avons déjà rencontré un élément.

Créez un nouveau fichier nommé loop_approach.py :

## Utilisation d'une boucle et d'un ensemble pour préserver l'ordre
fruits = ["apple", "banana", "orange", "apple", "pear", "banana"]

unique_fruits = []
seen = set()

for fruit in fruits:
    if fruit not in seen:
        seen.add(fruit)
        unique_fruits.append(fruit)

print("Liste originale:", fruits)
print("Éléments uniques (ordre préservé):", unique_fruits)

Exécutez le fichier :

python3 loop_approach.py

La sortie devrait être :

Original list: ['apple', 'banana', 'orange', 'apple', 'pear', 'banana']
Unique elements (order preserved): ['apple', 'banana', 'orange', 'pear']

Les trois méthodes obtiennent le même résultat : supprimer les doublons tout en préservant l'ordre de la première occurrence de chaque élément.

Exemple pratique : Analyse de données textuelles

Appliquons ce que nous avons appris à un exemple concret : l'analyse de la fréquence des mots dans un texte tout en préservant l'ordre de la première apparition.

Création d'un outil d'analyse de texte

Créez un nouveau fichier nommé text_analyzer.py :

def analyze_text(text):
    """
    Analyser le texte pour trouver les mots uniques dans l'ordre de leur première apparition
    et leurs fréquences.
    """
    ## Diviser le texte en mots et convertir en minuscules
    words = text.lower().split()

    ## Supprimer la ponctuation des mots
    clean_words = [word.strip('.,!?:;()[]{}""\'') for word in words]

    ## Compter la fréquence tout en préservant l'ordre
    word_counts = {}
    unique_words_in_order = []

    for word in clean_words:
        if word and word not in word_counts:
            unique_words_in_order.append(word)
        word_counts[word] = word_counts.get(word, 0) + 1

    return unique_words_in_order, word_counts

## Exemple de texte
sample_text = """
Python is amazing. Python is also easy to learn.
With Python, you can create web applications, data analysis tools,
machine learning models, and much more. Python has many libraries
that make development faster. Python is versatile!
"""

## Analyser le texte
unique_words, word_frequencies = analyze_text(sample_text)

## Afficher les résultats
print("Exemple de texte:")
print(sample_text)
print("\nMots uniques dans l'ordre de leur première apparition:")
print(unique_words)
print("\nFréquences des mots:")
for word in unique_words:
    if word:  ## Ignorer les chaînes vides
        print(f"'{word}': {word_frequencies[word]} fois")

Exécutez le fichier :

python3 text_analyzer.py

La sortie affichera les mots uniques dans l'ordre de leur première apparition dans le texte, ainsi que leurs fréquences :

Text sample:

Python is amazing. Python is also easy to learn.
With Python, you can create web applications, data analysis tools,
machine learning models, and much more. Python has many libraries
that make development faster. Python is versatile!

Unique words in order of first appearance:
['python', 'is', 'amazing', 'also', 'easy', 'to', 'learn', 'with', 'you', 'can', 'create', 'web', 'applications', 'data', 'analysis', 'tools', 'machine', 'learning', 'models', 'and', 'much', 'more', 'has', 'many', 'libraries', 'that', 'make', 'development', 'faster', 'versatile']

Word frequencies:
'python': 5 times
'is': 3 times
'amazing': 1 times
'also': 1 times
...

Amélioration de l'outil

Améliorons notre analyseur de texte pour gérer des scénarios plus complexes. Créez un fichier nommé improved_analyzer.py :

from collections import OrderedDict

def analyze_text_improved(text):
    """
    Une version améliorée de l'analyseur de texte qui gère des scénarios plus complexes
    et fournit plus de statistiques.
    """
    ## Diviser le texte en mots et convertir en minuscules
    words = text.lower().split()

    ## Supprimer la ponctuation des mots
    clean_words = [word.strip('.,!?:;()[]{}""\'') for word in words]

    ## Utiliser OrderedDict pour préserver l'ordre et compter la fréquence
    word_counts = OrderedDict()

    for word in clean_words:
        if word:  ## Ignorer les chaînes vides
            word_counts[word] = word_counts.get(word, 0) + 1

    ## Obtenir des statistiques
    total_words = sum(word_counts.values())
    unique_words_count = len(word_counts)

    return list(word_counts.keys()), word_counts, total_words, unique_words_count

## Exemple de texte
sample_text = """
Python is amazing. Python is also easy to learn.
With Python, you can create web applications, data analysis tools,
machine learning models, and much more. Python has many libraries
that make development faster. Python is versatile!
"""

## Analyser le texte
unique_words, word_frequencies, total_count, unique_count = analyze_text_improved(sample_text)

## Afficher les résultats
print("Exemple de texte:")
print(sample_text)
print("\nStatistiques:")
print(f"Nombre total de mots: {total_count}")
print(f"Mots uniques: {unique_count}")
print(f"Ratio d'unicité: {unique_count/total_count:.2%}")

print("\nLes 5 mots les plus fréquents:")
sorted_words = sorted(word_frequencies.items(), key=lambda x: x[1], reverse=True)
for word, count in sorted_words[:5]:
    print(f"'{word}': {count} fois")

Exécutez le fichier :

python3 improved_analyzer.py

Vous devriez voir une sortie avec des statistiques supplémentaires :

Text sample:

Python is amazing. Python is also easy to learn.
With Python, you can create web applications, data analysis tools,
machine learning models, and much more. Python has many libraries
that make development faster. Python is versatile!

Statistics:
Total words: 38
Unique words: 30
Uniqueness ratio: 78.95%

Top 5 most frequent words:
'python': 5 times
'is': 3 times
'to': 1 times
'learn': 1 times
'with': 1 times

Cet exemple pratique démontre comment la préservation de l'ordre des éléments lors de la suppression des doublons peut être utile dans des applications réelles comme l'analyse de texte.

Comparaison des performances et meilleures pratiques

Maintenant que nous avons exploré plusieurs méthodes pour convertir une liste en un ensemble tout en préservant l'ordre, comparons leurs performances et établissons quelques bonnes pratiques.

Création d'un test de performance

Créez un nouveau fichier nommé performance_test.py :

import time
from collections import OrderedDict

def method1_dict(data):
    """Using dict.fromkeys()"""
    return list(dict.fromkeys(data))

def method2_ordereddict(data):
    """Using OrderedDict.fromkeys()"""
    return list(OrderedDict.fromkeys(data))

def method3_loop(data):
    """Using a loop and a set"""
    result = []
    seen = set()
    for item in data:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

def time_function(func, data, runs=100):
    """Measure execution time of a function"""
    start_time = time.time()
    for _ in range(runs):
        func(data)
    end_time = time.time()
    return (end_time - start_time) / runs

## Test data
small_list = list(range(100)) + list(range(50))  ## 150 items, 50 duplicates
medium_list = list(range(1000)) + list(range(500))  ## 1500 items, 500 duplicates
large_list = list(range(10000)) + list(range(5000))  ## 15000 items, 5000 duplicates

## Test results
print("Performance comparison (average time in seconds over 100 runs):\n")

print("Small list (150 items, 50 duplicates):")
print(f"dict.fromkeys():       {time_function(method1_dict, small_list):.8f}")
print(f"OrderedDict.fromkeys(): {time_function(method2_ordereddict, small_list):.8f}")
print(f"Loop and set:          {time_function(method3_loop, small_list):.8f}")

print("\nMedium list (1,500 items, 500 duplicates):")
print(f"dict.fromkeys():       {time_function(method1_dict, medium_list):.8f}")
print(f"OrderedDict.fromkeys(): {time_function(method2_ordereddict, medium_list):.8f}")
print(f"Loop and set:          {time_function(method3_loop, medium_list):.8f}")

print("\nLarge list (15,000 items, 5,000 duplicates):")
print(f"dict.fromkeys():       {time_function(method1_dict, large_list):.8f}")
print(f"OrderedDict.fromkeys(): {time_function(method2_ordereddict, large_list):.8f}")
print(f"Loop and set:          {time_function(method3_loop, large_list):.8f}")

Exécutez le test de performance :

python3 performance_test.py

La sortie affichera la performance de chaque méthode avec différentes tailles de liste :

Performance comparison (average time in seconds over 100 runs):

Small list (150 items, 50 duplicates):
dict.fromkeys():       0.00000334
OrderedDict.fromkeys(): 0.00000453
Loop and set:          0.00000721

Medium list (1,500 items, 500 duplicates):
dict.fromkeys():       0.00003142
OrderedDict.fromkeys(): 0.00004123
Loop and set:          0.00007621

Large list (15,000 items, 5,000 duplicates):
dict.fromkeys():       0.00035210
OrderedDict.fromkeys(): 0.00044567
Loop and set:          0.00081245

Les chiffres réels peuvent varier en fonction de votre système, mais vous devriez remarquer certaines tendances.

Bonnes pratiques

Basées sur nos expériences, établissons quelques bonnes pratiques. Créez un fichier nommé best_practices.py :

"""
Best Practices for Converting a List to a Set While Preserving Order
"""

## Example 1: For Python 3.7+, use dict.fromkeys() for best performance
def preserve_order_modern(lst):
    """Best method for Python 3.7+ - using dict.fromkeys()"""
    return list(dict.fromkeys(lst))

## Example 2: For compatibility with older Python versions, use OrderedDict
from collections import OrderedDict

def preserve_order_compatible(lst):
    """Compatible method for all Python versions - using OrderedDict"""
    return list(OrderedDict.fromkeys(lst))

## Example 3: When you need to process elements while preserving order
def preserve_order_with_processing(lst):
    """Process elements while preserving order"""
    result = []
    seen = set()

    for item in lst:
        ## Option to process the item here
        processed_item = str(item).lower()  ## Example processing

        if processed_item not in seen:
            seen.add(processed_item)
            result.append(item)  ## Keep original item in the result

    return result

## Demo
data = ["Apple", "banana", "Orange", "apple", "Pear", "BANANA"]

print("Original list:", data)
print("Method 1 (Python 3.7+):", preserve_order_modern(data))
print("Method 2 (Compatible):", preserve_order_compatible(data))
print("Method 3 (With processing):", preserve_order_with_processing(data))

Exécutez le fichier :

python3 best_practices.py

La sortie montre comment chaque méthode gère les données :

Original list: ['Apple', 'banana', 'Orange', 'apple', 'Pear', 'BANANA']
Method 1 (Python 3.7+): ['Apple', 'banana', 'Orange', 'apple', 'Pear', 'BANANA']
Method 2 (Compatible): ['Apple', 'banana', 'Orange', 'apple', 'Pear', 'BANANA']
Method 3 (With processing): ['Apple', 'Orange', 'Pear']

Notez que la méthode 3 considère "Apple" et "apple" comme le même élément en raison du traitement en minuscules.

Recommandations

Basées sur nos expériences, voici quelques recommandations :

  1. Pour Python 3.7 et versions ultérieures, utilisez dict.fromkeys() pour les meilleures performances.
  2. Pour la compatibilité avec toutes les versions de Python, utilisez OrderedDict.fromkeys().
  3. Lorsque vous devez effectuer un traitement personnalisé tout en vérifiant les doublons, utilisez l'approche de la boucle et de l'ensemble.
  4. Tenez compte de la sensibilité à la casse et d'autres transformations en fonction de vos exigences spécifiques.

Résumé

Dans ce tutoriel, vous avez appris :

  1. Les différences fondamentales entre les listes et les ensembles (sets) Python

  2. Pourquoi la conversion d'une liste en un ensemble entraîne normalement la perte de l'ordre

  3. Plusieurs méthodes pour convertir une liste en un ensemble tout en préservant l'ordre d'origine :

    • Utilisation de dict.fromkeys() dans Python 3.7+
    • Utilisation de OrderedDict.fromkeys() pour la compatibilité avec les anciennes versions de Python
    • Utilisation d'une boucle avec un ensemble pour un traitement plus complexe
  4. Comment appliquer ces techniques à des problèmes concrets comme l'analyse de texte

  5. Les considérations de performance et les meilleures pratiques pour différents scénarios

Ces techniques sont précieuses pour le nettoyage des données, la suppression des doublons des entrées utilisateur, le traitement des options de configuration et de nombreuses autres tâches de programmation courantes. En choisissant l'approche appropriée en fonction de vos exigences spécifiques, vous pouvez écrire du code Python plus propre et plus efficace.