Obtenir les valeurs uniques d'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']

la sortie dont j'ai besoin est:

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

This un code qui fonctionne:

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

est-il une meilleure solution que je devrais utiliser?

522
demandé sur ArtOfWarfare 2012-10-15 18:05:37

30 réponses

déclarez D'abord votre liste correctement, séparées 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'utiliser comme une liste, vous devez le convertir en retour à la liste en faisant:

mynewlist = list(myset)

une Autre possibilité, probablement plus rapide serait d'utiliser un set 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 pas maintenir l'ordre original. Si vous en avez besoin, vous devriez consulter le ensemble commandé .

704
répondu lefterav 2017-07-17 20:05:54

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

mylist = list(set(mylist))
219
répondu alemol 2016-05-27 13:18:00

l'exemple que vous avez fourni ne correspond pas aux listes en Python. Ça ressemble à un dicton imbriqué, ce qui n'est probablement pas ce que vous vouliez.

une liste de Python:

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

pour obtenir des articles uniques, il suffit de le transformer en un ensemble (que vous pouvez transformer à nouveau dans une liste si nécessaire):

b = set(a)
print b
>>> set(['a', 'b', 'c', 'd'])
70
répondu Nicolas Barbey 2017-05-20 05:37:35

si nous avons besoin de maintenir l'ordre des éléments, que pensez-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 une autre 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 - 1er octobre 2016

une autre solution avec reduce , mais cette fois sans .append ce qui le rend plus lisible 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: ayez à l'esprit que plus nous lisons, plus le script est non-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.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

ANSWERING COMMENTS

parce que @monica a posé une bonne question sur "comment cela fonctionne-t-il?". Pour tous ceux qui ont des problèmes à le découvrir. Je vais essayer de donner une explication plus profonde sur la façon dont cela fonctionne et ce qui sorcellerie se passe ici ;)

donc 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 pas les résultats désirés à l'intérieur de la variable unique , mais seulement à l'intérieur de la variable used . C'est parce que pendant la compréhension de la liste .append modifie le used variable et retourne None .

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

Mais si nous sommes trop naïfs et juste aller avec:

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

nous n'obtiendrons rien en retour.

à nouveau, c'est parce que la .append méthode retourne None , et cela donne sur notre expression logique le regard suivant:

x not in used and None

Ce ne sera toujours:

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

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

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

Eh bien c'est parce que c'est ainsi que court-circuit opérateurs fonctionne de Python .

l'expression x and y évalue d'abord x; si x est fausse, sa valeur est retour; sinon, y est évalué et la valeur résultante est retourner.

quand x n'est pas utilisée (c'est à dire lorsque son 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 pour obtenir le éléments uniques d'une liste avec des doublons, nous voulons les .append dans une nouvelle liste que lorsque nous ils sont venus à travers pour une première fois.

donc nous voulons vraiment évaluer used.append(x) seulement quand x n'est pas dans used , peut-être que s'il y a un moyen de transformer cette valeur None en une valeur truthy nous serons très bien, non?

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

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

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

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

donc nous pouvons évaluer used.append(x) et obtenir True comme un résultat, seulement quand la première partie de l'expression (x not in used) est True .

on peut voir la même chose 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. ajouter x à l et retourner que l quand x n'est pas dans l . Merci à la or déclaration .append est évalué et l est retourné après cela.
  2. Retour l intact lorsque x est dans l
60
répondu Todor 2017-03-14 07:56:57

quel type est votre variable de sortie?

Python jeux sont ce que 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 de sortie.ajouter(elem) et assurez-vous qu'ils sont uniques.

Avertissement: des ensembles de NE PAS conserver l'original de l'ordre de la liste.

53
répondu Samuele Mattiuzzo 2016-07-21 17:06:19

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))
31
répondu daino3 2018-02-07 17:08:06

C'est la solution la plus simple-

list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
list=set(list)
18
répondu user3503711 2018-02-26 04:03:52

set-collection sans ordre d'éléments uniques. Liste des éléments peuvent être transmises à l'ensemble du constructeur. Ainsi, passer la liste avec des éléments dupliqués, nous obtenons mis avec des éléments uniques et le transformer de nouveau à la liste puis obtenir la liste avec des éléments uniques. Je ne peux rien dire sur la performance et la mémoire, mais j'espère que ce n'est pas si important avec de petites listes.

list(set(my_not_unique_list))

simple et court.

15
répondu MultiTeemer 2016-01-05 20:01:03

même ordre liste unique utilisant seulement 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 comme un tuple .

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

Modifier

je dois noter que ce n'est pas une bonne façon de le faire, du point de vue de la performance. C'est juste une façon qui l'atteint en utilisant seulement une compression de liste.

12
répondu OdraEncoded 2015-08-11 16:45:23

si vous utilisez numpy dans votre code (ce qui pourrait être un bon choix pour de plus grandes quantités de données), consultez 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 voir, numpy supporte non seulement les données numériques, les tableaux de chaînes de caractères sont également possibles. Bien sûr, le résultat est un numpy tableau, mais il n'a pas d'importance beaucoup, parce qu'il est encore se comporte comme une séquence:

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

si vous voulez vraiment avoir une liste de Python à la vanille, vous pouvez toujours appeler list().

cependant, le résultat est automatiquement trié, comme vous pouvez le voir à partir des fragments de code ci-dessus. Vérifier numpy unique sans tri si l'ordre de liste de conservation est nécessaire.

12
répondu maclav3 2017-05-23 11:47:28

obtenir des éléments uniques de la liste

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

utilisant la logique Simple de Sets-Sets sont une liste unique d'articles

mylist=list(set(mylist))

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

À L'Aide De Simple Logique

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]

utilisant la méthode pop ->pop supprime le dernier ou l'é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]

Utilisation De 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

11
répondu Saqib Mujtaba 2018-02-02 10:51:23

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']

supposez Si ci-dessus est la liste d'exemple. Ensuite, vous pouvez utiliser la recette suivante comme donner l'exemple d'itertools doc qui peut retourner les valeurs uniques et préserver l'ordre comme vous semblez avoir besoin. L'itérable ici est l'example_list

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
répondu Senthil Kumaran 2012-10-15 14:12:00

en utilisant la propriété de base du dictionnaire Python:

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

sortie sera:

set([u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow'])
6
répondu SOUBHIK RAKSHIT 2018-03-30 05:08:45
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
5
répondu oliver smith 2016-01-25 10:11:56
def setlist(lst=[]):
   return list(set(lst))
4
répondu Ricky Wilson 2014-06-16 08:25:16

en bonus, 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)
4
répondu Berislav Lopac 2016-06-16 11:57:23

en plus des réponses précédentes, qui disent que vous pouvez convertir votre liste en set, 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)]

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 les sets)

>>> t = [v for i,v in enumerate(mylist) if mylist.index(v) == i]
[u'nowplaying', u'PBS', u'job', u'debate', u'thenadnow']
4
répondu Alaf Azam 2017-06-17 07:45:50

pour obtenir des valeurs uniques de votre code d'utilisation de la liste 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 d'une liste n'est pas hachable 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 trends liste ne contient toujours que des éléments hachurables sinon vous devez 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
3
répondu Andriy Ivaneyko 2016-08-05 09:57:35

je suis surpris que personne jusqu'à présent n'ait donné une réponse directe de maintien de 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 de sorte qu'il fonctionne avec plus que de simples listes, par exemple unique(range(10)) . Pour obtenir une liste, il suffit d'appeler 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 a l'exigence que chaque élément est hachable et pas seulement comparable, mais la plupart des choses en Python est et il est O(N) et non O(N^2), donc fonctionnera très bien avec une longue liste.

3
répondu olau 2017-03-02 11:28:13
  1. au début de votre code, déclarez que votre liste de sortie est vide: output=[]
  2. au lieu de votre code vous pouvez utiliser ce code trends=list(set(trends))
2
répondu Sanjar Stone 2014-02-04 00:41:47

Vous pouvez utiliser des ensembles. Juste pour être clair, je vais expliquer quelle est la différence entre une liste et un ensemble. les décors sont une collection sans ordre d'éléments uniques.Les listes sont ordonnées collection d'éléments. So,

    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. Il sera la cause de l'erreur: EX: Au lieu d'utiliser la liste au lieu de unicode_list dans la précédente.

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
répondu phanindravarma 2017-02-06 20:52:32

set peut vous aider à filtrer les éléments de la liste sont des doublons. Cela fonctionnera bien pour les éléments str , int ou tuple , mais si votre liste contient dict ou d'autres list , alors vous finirez avec des exceptions TypeError .

Voici une solution générale de conservation des commandes pour traiter certains (pas tous) types non-hachables:

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
2
répondu Régis B. 2018-04-04 19:20:21

ensemble est une collection d'éléments ordonnés et uniques. Ainsi, vous pouvez utiliser défini 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
répondu Tung Nguyen 2016-06-05 07:57:56

ma solution pour vérifier le contenu pour l'unicité mais préserver l'ordre original:

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: Probablement peut être plus efficace en utilisant des clés de dictionnaire pour vérifier l'existence au lieu de faire une boucle de dossier entière pour chaque ligne, Je ne voudrais pas utiliser ma solution pour les grands ensembles.

1
répondu Neo 2017-05-26 12:37:39
from collections import OrderedDict


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

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

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

alternativement en Python 3.6+:

# Order-preserving
list(dict.fromkeys(seq))
# Out: ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']
1
répondu pylang 2017-12-29 20:25:35

utiliser set pour supprimer une liste, retourner comme liste

def get_unique_list(lst):
        if isinstance(lst,list):
            return list(set(lst))
1
répondu Goran B. 2018-03-02 19:21:16

Pour les longs tableaux

s = np.empty(len(var))

s[:] = np.nan

for  x in  set(var):

    x_positions = np.where(var==x)

    s[x_positions[0][0]]=x


sorted_var=s[~np.isnan(s)]
0
répondu user5028205 2015-06-19 12:30:37

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 voulez ajouter uniquement des éléments à une liste, vous appelez simplement annexe sur une liste unique. Parce qu'il hérite d'une liste, il agit essentiellement comme une liste, donc vous pouvez utiliser des fonctions comme index() etc. Et parce qu'il retourne true ou false, vous pouvez savoir si Ajouter réussi (unique item) ou échoué (déjà dans la liste).

à obtenez une liste unique d'éléments d'une liste, utilisez une boucle pour ajouter des éléments à une liste unique (puis copiez sur la liste).

exemple de code d'usage:

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)

Imprime:

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

Copie de la liste:

unique = UniqueList()

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

newlist = unique[:]
print newlist

Imprime:

[1, 2, 3, 4]
0
répondu c1646091 2016-07-16 08:04:27

si vous voulez obtenir des éléments uniques d'une liste et garder leur ordre original, alors vous pouvez employer OrderedDict structure de données 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 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 " des dicts. Regardez ici . Bien que cela "ait considéré un détail de mise en œuvre et ne devrait pas être comptée".

0
répondu skovorodkin 2016-10-01 22:01:18

essayez cette fonction, c'est similaire à votre code mais c'est une plage dynamique.

def unique(a):

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



    return a
-3
répondu CreamStat 2014-08-17 00:44:37