Question Obtenir des valeurs uniques dans une liste en python [dupliquer]


Cette question a déjà une réponse ici:

Je veux obtenir les valeurs uniques de la liste suivante:

[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']

Le résultat que je demande est:

[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']

Ce code fonctionne:

output = []
for x in trends:
    if x not in output:
        output.append(x)
print output

Y a-t-il une meilleure solution que je devrais utiliser?


492
2017-10-15 14:05


origine


Réponses:


Commencez par déclarer votre liste correctement, en la séparant par des virgules. Vous pouvez obtenir les valeurs uniques en convertissant la liste en un ensemble.

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
myset = set(mylist)
print myset

Si vous l'utilisez plus en tant que liste, vous devriez le convertir en liste en faisant:

mynewlist = list(myset)

Une autre possibilité, probablement plus rapide serait d'utiliser un ensemble depuis le début, au lieu d'une liste. Alors votre code devrait être:

output = set()
for x in trends:
    output.add(x)
print output

Comme il a été souligné, les ensembles ne conservent pas l'ordre d'origine. Si vous en avez besoin, vous devriez consulter le set commandé.


681
2017-10-15 14:11



Pour être cohérent avec le type je voudrais utiliser:

mylist = list(set(mylist))

205
2017-12-04 23:02



L'exemple que vous avez fourni ne correspond pas aux listes en Python. Cela ressemble à un dict imbriqué, ce qui n'est probablement pas ce que vous vouliez.

Une liste Python:

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

Pour obtenir des éléments uniques, transformez-le en un ensemble (que vous pouvez reconvertir en une liste si nécessaire):

b = set(a)
print b
>>> set(['a', 'b', 'c', 'd'])

66
2017-10-15 14:11



Si nous devons garder l'ordre des éléments, qu'en est-il de ceci:

used = set()
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for x in mylist if x not in used and (used.add(x) or True)]

Et une solution de plus en utilisant reduce et sans le temporaire used var.

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])

MISE À JOUR - 1er octobre 2016

Une autre solution avec reducemais cette fois sans .append ce qui le rend plus lisible par l'homme et plus facile à comprendre.

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])
#which can also be writed as:
unique = reduce(lambda l, x: l if x in l else l+[x], mylist, [])

REMARQUE: Gardez à l'esprit que plus nous lisons humainement, plus le script est inefficace.

import timeit

setup = "mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']"

#10x to Michael for pointing out that we can get faster with set()
timeit.timeit('[x for x in mylist if x not in used and (used.add(x) or True)]', setup='used = set();'+setup)
0.4188511371612549

timeit.timeit('[x for x in mylist if x not in used and (used.append(x) or True)]', setup='used = [];'+setup)
0.8063139915466309

timeit.timeit('reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])', setup=setup)
2.216820001602173

timeit.timeit('reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])', setup=setup)
2.948796033859253

timeit.timeit('reduce(lambda l, x: l if x in l else l+[x], mylist, [])', setup=setup)
2.9785239696502686

RÉPONDRE AUX COMMENTAIRES 

Car @monica posé une bonne question sur "comment ça marche?". Pour tout le monde ayant des problèmes à comprendre. Je vais essayer de donner une explication plus profonde sur comment cela fonctionne et quelle sorcellerie se passe ici;)

Alors elle a d'abord demandé:

J'essaie de comprendre pourquoi unique = [used.append(x) for x in mylist if x not in used] ne fonctionne pas.

Eh bien ça marche vraiment

>>> used = []
>>> mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> unique = [used.append(x) for x in mylist if x not in used]
>>> print used
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
>>> print unique
[None, None, None, None, None]

Le problème est que nous n’obtenons pas les résultats escomptés à l’intérieur du unique variable, mais seulement à l'intérieur du used variable. C'est parce que pendant la compréhension de la liste .append modifie le used variable et retours None.

Donc, pour obtenir les résultats dans le unique variable, et toujours utiliser la même logique avec .append(x) if x not in used, nous devons déplacer cela .append appeler sur le côté droit de la compréhension de la liste et juste revenir x sur le côté gauche.

Mais si nous sommes trop naïfs et que nous partons avec:

>>> unique = [x for x in mylist if x not in used and used.append(x)]
>>> print unique
[]

Nous n'obtiendrons rien en retour.

Encore une fois, c'est parce que le .append retour de méthode None, et cela donne sur notre expression logique le regard suivant:

x not in used and None

Cela va essentiellement toujours:

  1. évalue à False quand x est dans used,
  2. évalue à None quand x n'est pas dans used.

Et dans les deux cas (False/None), cela sera traité comme falsy valeur et nous obtiendrons une liste vide en conséquence.

Mais pourquoi cela évalue None quand x n'est pas dans used? Quelqu'un peut demander.

Eh bien c'est parce que c'est comment Python court-circuit les opérateurs travaux.

L'expression x and y évalue d'abord x; si x est faux, sa valeur est   revenu; sinon, y est évalué et la valeur résultante est   revenu.

Donc quand x n'est pas utilisé (c'est-à-dire quand True) la prochaine partie ou l'expression sera évaluée (used.append(x)) et sa valeur (None) sera retourné.

Mais c'est ce que nous voulons afin d'obtenir les éléments uniques d'une liste avec des doublons, nous voulons .append eux dans une nouvelle liste seulement quand nous nous sommes rencontrés pour une première fois.

Nous voulons donc vraiment évaluer used.append(x) seulement quand x n'est pas dans used, peut-être s'il y a un moyen de tourner cette None valeur dans un truthy celui que nous irons bien, non?

Eh bien, oui et voici où le 2ème type de short-circuit les opérateurs viennent jouer.

L'expression x or y évalue d'abord x; si x est vrai, sa valeur est   revenu; sinon, y est évalué et la valeur résultante est   revenu.

Nous savons que .append(x) sera toujours falsy, donc si on ajoute juste un or à côté de lui, nous aurons toujours la prochaine partie. C'est pourquoi nous écrivons:

x not in used and (used.append(x) or True)

afin que nous puissions évaluer  used.append(x) et obtenir True Par conséquent, seulement quand la première partie de l'expression (x not in used) est True.

On peut voir une mode similaire dans la 2ème approche avec le reduce méthode.

(l.append(x) or l) if x not in l else l
#similar as the above, but maybe more readable
#we return l unchanged when x is in l
#we append x to l and return l when x is not in l
l if x in l else (l.append(x) or l)

où nous:

  1. Ajouter x à l et retourne ça l quand x n'est pas dans l. Grace à or déclaration .append est évalué et l est retourné après cela.
  2. Revenir l intact quand x est dans l

56
2018-05-11 12:49



quel type est votre variable de sortie?

Python ensembles sont ce dont vous avez juste besoin. Déclarez la sortie comme ceci:

output = set([]) # initialize an empty set

et vous êtes prêt à ajouter des éléments avec output.add (elem) et assurez-vous qu'ils sont uniques.

Attention: les jeux ne conservent pas l'ordre d'origine de la liste.


50
2017-10-15 14:07



Maintien de l'ordre:

# oneliners
# slow -> . --- 14.417 seconds ---
[x for i, x in enumerate(array) if x not in array[0:i]]

# fast -> . --- 0.0378 seconds ---
[x for i, x in enumerate(array) if array.index(x) == i]

# multiple lines
# fastest -> --- 0.012 seconds ---
uniq = []
[uniq.append(x) for x in array if x not in uniq]
uniq

L'ordre n'a pas d'importance:

# fastest-est -> --- 0.0035 seconds ---
list(set(array))

26
2017-07-03 20:36



C'est une solution simple

list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
list=set(list)

17
2018-02-26 04:03



set - collection non ordonnée d'éléments uniques. La liste des éléments peut être passée au constructeur de set. Donc, passer la liste avec les éléments en double, nous obtenons des éléments uniques et nous la transformons en liste, puis obtenons la liste avec des éléments uniques. Je ne peux rien dire au sujet des performances et de la mémoire, mais j'espère que ce n'est pas si important avec les petites listes.

list(set(my_not_unique_list))

Simplement et court.


15
2018-02-06 12:16