web-dev-qa-db-fra.com

Obtenir des valeurs uniques à partir d'une liste dans python

Je veux obtenir les valeurs uniques de la liste suivante:

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

La sortie dont j'ai besoin 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?

666
savitha

Commencez par déclarer votre liste correctement, en les séparant par une virgule. 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 encore comme liste, vous devriez le reconvertir en faisant ceci:

mynewlist = list(myset)

Une autre possibilité, probablement plus rapide, serait d'utiliser un ensemble depuis le début, au lieu d'une liste. Ensuite, 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 vous renseigner sur le ensemble ordonné .

869
lefterav

Pour être cohérent avec le type que j'utiliserais:

mylist = list(set(mylist))
283
alemol

quel type est votre variable de sortie?

Python sets 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 ensembles ne conservent pas l'ordre d'origine de la liste.

82
Samuele Mattiuzzo

Si nous devons garder l'ordre des éléments, que diriez-vous 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 encore une solution 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 - Mars 2019

Et une troisième solution, qui est nette, mais assez lente puisque _.index_ est O (n).

_mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for i, x in enumerate(mylist) if i == mylist.index(x)]
_

UPDATE - Oct, 2016

Une autre solution avec reduce, mais cette fois sans _.append_, ce qui la 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, [])
_

NOTE: N'oubliez pas que plus le script est lisible par l'homme, plus le script est peu performant.

_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.6157128810882568

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

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

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

timeit.timeit('[x for i, x in enumerate(mylist) if i == mylist.index(x)]', setup=setup)
2.3621110916137695
_

RÉPONSE AUX COMMENTAIRES

Parce que @ monica a posé une bonne question sur "comment cela fonctionne-t-il?". Pour tout le monde ayant des problèmes pour le comprendre. Je vais essayer de donner une explication plus profonde sur la façon dont cela fonctionne et sur la sorcellerie qui 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

_>>> 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 tout simplement pas les résultats souhaités dans la variable unique, mais uniquement dans la variable used. En effet, lors de la compréhension de la liste, _.append_ modifie la variable used et renvoie None.

Donc, pour obtenir les résultats dans la variable unique et continuer à utiliser la même logique avec .append(x) if x not in used, nous devons déplacer cet appel _.append_ à droite de la liste compréhension et simplement retourne x du côté gauche.

Mais si nous sommes trop naïfs et allons simplement 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, cela est dû au fait que la méthode _.append_ renvoie None, ce qui donne à notre expression logique l'aspect suivant:

_x not in used and None
_

Ce sera essentiellement toujours:

  1. est évalué à False lorsque x est dans used,
  2. est évalué à None lorsque x n'est pas dans used.

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

Mais pourquoi ceci est évalué à None alors que x n'est pas dans used? Quelqu'un peut demander.

C'est parce que c'est comme ça que Python fonctionne court-circuit opérateurs fonctionne .

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

Ainsi, lorsque x n’est pas utilisé (c’est-à-dire lorsque sa True) la partie suivante ou l’expression sera évaluée ( used.append(x)) et sa valeur (None) seront renvoyés.

Mais c’est ce que nous voulons pour obtenir les éléments uniques d’une liste avec des doublons, nous voulons les _.append_ dans une nouvelle liste uniquement lorsqu’ils sont arrivés pour la première fois.

Donc, nous voulons vraiment évaluer used.append(x) uniquement lorsque x n'est pas dans used, peut-être s'il existe un moyen de transformer cette valeur None en une valeur truthy nous irons bien, non?

Eh bien oui et c’est ici que le 2e type d’opérateurs _short-circuit_ vient jouer.

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

Nous savons que .append(x) sera toujours falsy, donc si nous ajoutons juste un or à ses côtés, nous aurons toujours la partie suivante. 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 en conséquence, uniquement lorsque la première partie de l'expression (x not in used) est True.

Une approche similaire peut être observée dans la deuxième approche avec la méthode reduce.

_(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. Ajoutez x à l et renvoyez _ l lorsque x ne figure pas dans l. Grâce à l'instruction or, _.append_ est évalué et l est renvoyé par la suite.
  2. Retourne l intacte lorsque x est dans l
81
Todor

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 objets uniques, transformez-le simplement en un ensemble (que vous pourrez reconvertir ultérieurement en liste si nécessaire):

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

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))
40
daino3

C'est une solution simple

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

Obtenir des éléments uniques de la liste

mylist = [1,2,3,4,5,6,6,7,7,8,8,9,9,10]

Utilisation de la logique simple à partir d'ensembles - Les ensembles sont une liste unique d'éléments

mylist=list(set(mylist))

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Utiliser la logique simple

newList=[]
for i in mylist:
    if i not in newList:
        newList.append(i)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Utiliser la méthode pop -> pop supprime le dernier élément indexé et l’affiche à l’utilisateur. vidéo

k=0
while k < len(mylist):
    if mylist[k] in mylist[k+1:]:
        mylist.pop(mylist[k])
    else:
        k=k+1

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Utiliser Numpy

import numpy as np
np.unique(mylist)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

référence

19
Saqib Mujtaba

set - collection non ordonnée d'éléments uniques. La liste des éléments peut être passée au constructeur de set. Donc, liste de passage avec des éléments en double, nous obtenons des éléments uniques et le transformons en liste puis nous obtenons une liste avec des éléments uniques. Je ne peux rien dire sur les performances et la surcharge de 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
MultiTeemer

Si vous utilisez numpy dans votre code (ce qui pourrait être un bon choix pour de plus grandes quantités de données), vérifiez numpy.unique :

>>> import numpy as np
>>> wordsList = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> np.unique(wordsList)
array([u'PBS', u'debate', u'job', u'nowplaying', u'thenandnow'], 
      dtype='<U10')

( http://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html )

Comme vous pouvez le constater, numpy prend en charge non seulement les données numériques, mais également les tableaux de chaînes. Bien sûr, le résultat est un tableau numpy, mais cela n'a pas beaucoup d'importance, car il se comporte toujours comme une séquence:

>>> for Word in np.unique(wordsList):
...     print Word
... 
PBS
debate
job
nowplaying
thenandnow

Si vous voulez vraiment avoir une liste Vanilla python, vous pouvez toujours appeler list ().

Cependant, le résultat est automatiquement trié, comme le montrent les fragments de code ci-dessus. Départ numpy unique sans tri si le maintien de l'ordre de la liste est requis.

15
maclav3

Voici un résumé sur l'obtention d'éléments uniques, non ordonnés ou ordonnés.

Étant donné

from collections import OrderedDict


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

Code

# Unordered
list(set(seq))
# Out: ['thenandnow', 'PBS', 'debate', 'job', 'nowplaying']

# Order-preserving
list(OrderedDict.fromkeys(seq))
# Out: ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']

Sinon, dans Python 3.6+:

# Order-preserving
list(dict.fromkeys(seq))
# Out: ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']

Remarque: les éléments listés doivent être hashable . Voir aussi les détails sur ce dernier exemple dans ce article de blog . En outre, voir post de R. Hettinger sur la même technique; l'ordre de préservation dict est étendu à partir de l'une de ses premières applications.

13
pylang

Liste unique du même ordre utilisant uniquement une compression de liste.

> my_list = [1, 2, 1, 3, 2, 4, 3, 5, 4, 3, 2, 3, 1]
> unique_list = [
>    e
>    for i, e in enumerate(my_list)
>    if my_list.index(e) == i
> ]
> unique_list
[1, 2, 3, 4, 5]

enumerates donne l'indice i et l'élément e sous la forme d'un Tuple.

my_list.index renvoie le premier index de e. Si le premier index n'est pas i, l'itération en cours e n'est pas le premier e de la liste.

Éditer

Je dois noter que ce n'est pas une bonne façon de le faire, en termes de performances. Ceci est juste une manière de le réaliser en utilisant uniquement une compression de liste.

12
OdraEncoded

En utilisant la propriété de base de Python Dictionary:

inp=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
d={i for i in inp}
print d

La sortie sera:

set([u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow'])
8
SOUBHIK RAKSHIT
def get_distinct(original_list):
    distinct_list = []
    for each in original_list:
        if each not in distinct_list:
            distinct_list.append(each)
    return distinct_list
6
oliver smith

set peut vous aider à filtrer les éléments en double de la liste. Cela fonctionnera bien pour les éléments str, int ou Tuple, mais si votre liste contient des éléments dict ou autres list, vous obtiendrez alors TypeError exceptions.

Voici une solution générale préservant les commandes pour gérer certains types (pas tous) non-hashable:

def unique_elements(iterable):
    seen = set()
    result = []
    for element in iterable:
        hashed = element
        if isinstance(element, dict):
            hashed = Tuple(sorted(element.iteritems()))
        Elif isinstance(element, list):
            hashed = Tuple(element)
        if hashed not in seen:
            result.append(element)
            seen.add(hashed)
    return result
6
Régis B.

Tout d’abord, l’exemple que vous avez donné n’est pas une liste valide.

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

Supposons que si ci-dessus est la liste d'exemple. Vous pouvez ensuite utiliser la recette suivante comme exemple pour la documentation itertools qui peut renvoyer les valeurs uniques et préserver l’ordre tel que vous semblez le nécessiter. L'iterable ici est la liste_exemples

from itertools import ifilterfalse

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in ifilterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element
6
Senthil Kumaran

En prime, Counter est un moyen simple d'obtenir à la fois les valeurs uniques et le nombre pour chaque valeur:

from collections import Counter
l = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
c = Counter(l)
5
Berislav Lopac
def setlist(lst=[]):
   return list(set(lst))
4
Ricky Wilson

Pour obtenir des valeurs uniques à partir de votre liste , utilisez le code ci-dessous:

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

IMPORTANT: L'approche ci-dessus ne fonctionnera pas si l'un des éléments de la liste n'est pas hashable , ce qui est le cas pour mutable types, par exemple liste ou dict .

trends = [{'super':u'nowplaying'}, u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  TypeError: unhashable type: 'dict'

Cela signifie que vous devez être sûr que la liste trends ne contiendra toujours que des éléments pouvant être hachés, sinon vous devrez utiliser un code plus sophistiqué:

from copy import deepcopy

try:
    trends = [{'super':u'nowplaying'}, [u'PBS',], [u'PBS',], u'nowplaying', u'job', u'debate', u'thenandnow', {'super':u'nowplaying'}]
    output = set(trends)
    output = list(output)
except TypeError:
    trends_copy = deepcopy(trends)
    while trends_copy:
        trend = trends_copy.pop()
        if trends_copy.count(trend) == 0:
            output.append(trend)
print output
4
Andriy Ivaneyko

En plus des réponses précédentes, qui disent que vous pouvez convertir votre liste pour définir, vous pouvez le faire de cette façon aussi

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenadnow']
mylist = [i for i in set(mylist)]

la sortie sera

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

bien que l'ordre ne soit pas préservé.

Une autre réponse plus simple pourrait être (sans utiliser des ensembles)

>>> t = [v for i,v in enumerate(mylist) if mylist.index(v) == i]
[u'nowplaying', u'PBS', u'job', u'debate', u'thenadnow']
4
Alaf Azam

Je suis surpris de constater que personne n'a jusqu'ici donné une réponse directe préservant l'ordre:

def unique(sequence):
    """Generate unique items from sequence in the order of first occurrence."""
    seen = set()
    for value in sequence:
        if value in seen:
            continue

        seen.add(value)

        yield value

Il générera les valeurs afin qu'il fonctionne avec plus que de simples listes, par exemple. unique(range(10)). Pour obtenir une liste, appelez simplement list(unique(sequence)), comme ceci:

>>> list(unique([u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']))
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']

Il est nécessaire que chaque élément soit haschable et non seulement comparable, mais la plupart des éléments de Python le soient et il s’agit de O(n) et non de O (n ^ 2). fonctionne très bien avec une longue liste.

3
olau

utiliser set pour dédupliquer une liste, retourner en tant que liste

def get_unique_list(lst):
        if isinstance(lst,list):
            return list(set(lst))
2
Goran B.
  1. Au début de votre code, déclarez simplement que votre liste de sortie est vide: output=[]
  2. Au lieu de votre code, vous pouvez utiliser ce code trends=list(set(trends))
2
Sanjar Stone

Vous pouvez utiliser des ensembles. Juste pour être clair, j'explique quelle est la différence entre une liste et un ensemble. Les ensembles sont une collection d'éléments non ordonnés. Les listes sont une collection d'éléments ordonnée. Alors,

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

Mais: N'utilisez pas list/set pour nommer les variables. Cela provoquera l'erreur suivante: EX: au lieu d'utiliser liste au lieu de liste_unicode dans la liste ci-dessus.

list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job',u'debate', u'thenandnow']
        list_unique=list(set(list))
        print list_unique
    list_unique=list(set(list))
TypeError: 'list' object is not callable
2
phanindravarma

Set est une collection d'éléments ordonnés et uniques. Donc, vous pouvez utiliser set comme ci-dessous pour obtenir une liste unique:

unique_list = list(set([u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']))
1
Tung Nguyen

Si vous souhaitez obtenir des éléments uniques d'une liste et conserver leur ordre d'origine, vous pouvez utiliser la structure de données OrderedDict de la bibliothèque standard de Python:

from collections import OrderedDict

def keep_unique(elements):
    return list(OrderedDict.fromkeys(elements).keys())

elements = [2, 1, 4, 2, 1, 1, 5, 3, 1, 1]
required_output = [2, 1, 4, 5, 3]

assert keep_unique(elements) == required_output

En fait, si vous utilisez Python ≥ 3.6, vous pouvez utiliser plain dict pour cela:

def keep_unique(elements):
    return list(dict.fromkeys(elements).keys())

C'est devenu possible après l'introduction de la représentation "compacte" de dict. Check it out ici . Bien que ceci "ait été considéré comme un détail de mise en œuvre et ne doit pas être invoqué".

1
skovorodkin

Ma solution pour vérifier l’unicité du contenu tout en préservant la commande initiale:

def getUnique(self):
    notunique = self.readLines()
    unique = []
    for line in notunique: # Loop over content
        append = True # Will be set to false if line matches existing line
        for existing in unique:
            if line == existing: # Line exists ? do not append and go to the next line
                append = False
                break # Already know file is unique, break loop
        if append: unique.append(line) # Line not found? add to list
    return unique

Edit: Peut probablement être plus efficace en utilisant des clés de dictionnaire pour vérifier l'existence au lieu de faire une boucle de fichier complète pour chaque ligne, je n'utiliserais pas ma solution pour les grands ensembles.

1
Neo

Je sais que c'est une vieille question, mais voici ma solution unique: l'héritage de classe !:

class UniqueList(list):
    def appendunique(self,item):
        if item not in self:
            self.append(item)
            return True
        return False

Ensuite, si vous souhaitez ajouter des éléments de manière unique à une liste, vous appelez simplement appendunique dans une UniqueList. Comme il hérite d’une liste, il agit essentiellement comme une liste. Vous pouvez donc utiliser des fonctions telles que index (), etc. Et comme il renvoie true ou false, vous pouvez savoir si l’ajout a réussi (élément unique) ou échoué (déjà dans les liste).

Pour obtenir une liste unique d'éléments dans une liste, utilisez une boucle for en ajoutant des éléments à une UniqueList (puis copiez-les dans la liste).

Exemple de code d'utilisation:

unique = UniqueList()

for each in [1,2,2,3,3,4]:
    if unique.appendunique(each):
        print 'Uniquely appended ' + str(each)
    else:
        print 'Already contains ' + str(each)

Impressions:

Uniquely appended 1
Uniquely appended 2
Already contains 2
Uniquely appended 3
Already contains 3
Uniquely appended 4

Copier pour lister:

unique = UniqueList()

for each in [1,2,2,3,3,4]:
    unique.appendunique(each)

newlist = unique[:]
print newlist

Impressions:

[1, 2, 3, 4]
0
c1646091