162 votes

La conversion d'une liste en un ensemble modifie l'ordre des éléments.

Récemment, j'ai remarqué que lorsque je convertissais un fichier list a set l'ordre des éléments est modifié et est trié par caractère.

Prenons cet exemple :

x=[1,2,20,6,210]
print x 
# [1, 2, 20, 6, 210] # the order is same as initial order

set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted

Mes questions sont -

  1. Pourquoi cela se produit-il ?
  2. Comment faire des opérations de set (notamment Set Difference) sans perdre l'ordre initial ?

149 votes

@KarlKnechtel - Oui "l'ordre est un concept sans signification pour les ensembles...en mathématiques" mais j'ai des problèmes du monde réel :)

1 votes

Sur CPython 3.6+ unique = list(dict.fromkeys([1, 2, 1]).keys()) . Cela fonctionne parce que dict s préserver l'ordre d'insertion maintenant.

9voto

Alex Ricciardi Points 41

Vous pouvez supprimer les valeurs dupliquées et conserver l'ordre d'insertion de la liste avec une seule ligne de code, Python 3.8.2

mylist = \['b', 'b', 'a', 'd', 'd', 'c'\]

results = list({value:"" for value in mylist})

print(results)

>>> \['b', 'a', 'd', 'c'\]

results = list(dict.fromkeys(mylist))

print(results)

>>> \['b', 'a', 'd', 'c'\]

7voto

jsbueno Points 22212

Comme indiqué dans d'autres réponses, les ensembles sont des structures de données (et des concepts mathématiques) qui ne préservent pas l'ordre des éléments.

Cependant, en utilisant une combinaison d'ensembles et de dictionnaires, il est possible d'obtenir tout ce que vous voulez - essayez d'utiliser ces extraits :

# save the element order in a dict:
x_dict = dict(x,y for y, x in enumerate(my_list) )
x_set = set(my_list)
#perform desired set operations
...
#retrieve ordered list from the set:
new_list = [None] * len(new_set)
for element in new_set:
   new_list[x_dict[element]] = element

1voto

jimh Points 573

En m'appuyant sur la réponse de Sven, j'ai trouvé que l'utilisation de collections.OrderedDict de cette manière m'a permis d'accomplir ce que vous voulez et d'ajouter plus d'éléments au dict :

import collections

x=[1,2,20,6,210]
z=collections.OrderedDict.fromkeys(x)
z
OrderedDict([(1, None), (2, None), (20, None), (6, None), (210, None)])

Si vous voulez ajouter des articles tout en les traitant comme un ensemble, vous pouvez le faire :

z['nextitem']=None

Et vous pouvez effectuer une opération comme z.keys() sur le dict et obtenir l'ensemble :

z.keys()
[1, 2, 20, 6, 210]

0voto

Mike Stucka Points 9

Une mise en œuvre du concept de score le plus élevé ci-dessus qui le ramène à une liste :

def SetOfListInOrder(incominglist):
    from collections import OrderedDict
    outtemp = OrderedDict()
    for item in incominglist:
        outtemp[item] = None
    return(list(outtemp))

Testé (brièvement) sur Python 3.6 et Python 2.7.

0voto

Ultrablendz Points 53

Dans le cas où vous avez un petit nombre d'éléments dans vos deux listes initiales sur lesquels vous voulez faire une opération de différence de jeu, au lieu d'utiliser collections.OrderedDict qui complique l'implémentation et la rend moins lisible, vous pouvez utiliser :

# initial lists on which you want to do set difference
>>> nums = [1,2,2,3,3,4,4,5]
>>> evens = [2,4,4,6]
>>> evens_set = set(evens)
>>> result = []
>>> for n in nums:
...   if not n in evens_set and not n in result:
...     result.append(n)
... 
>>> result
[1, 3, 5]

Sa complexité temporelle n'est pas très bonne mais il est soigné et facile à lire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X