Obtener valores únicos de una lista en python

Quiero obtener los valores únicos de la siguiente lista:

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

La salida que requiero es:

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

Este código funciona:

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

¿Hay una solución mejor que debería usar?

Primero declara tu lista correctamente, separados por comas. Puede obtener los valores únicos convirtiendo la lista en un conjunto.

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

Si lo usa más como una lista, debería convertirlo de nuevo a la lista haciendo lo siguiente:

 mynewlist = list(myset) 

Otra posibilidad, probablemente más rápida sería utilizar un conjunto desde el principio, en lugar de una lista. Entonces tu código debería ser:

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

Como se ha señalado, los conjuntos no mantienen el pedido original. Si lo necesita, debería consultar el conjunto ordenado .

Para ser consistente con el tipo que usaría:

 mylist = list(set(mylist)) 

¿De qué tipo es tu variable de salida?

Los conjuntos de Python son lo que necesitas. Declare la salida de esta manera:

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

y está listo para agregar elementos con output.add(elem) y asegurarse de que sean únicos.

Advertencia: los conjuntos NO conservan el orden original de la lista.

El ejemplo que proporcionó no corresponde a las listas en Python. Se asemeja a un dict nested, que probablemente no sea lo que pretendías.

Una lista de Python:

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

Para obtener elementos únicos, simplemente conviértalos en un conjunto (que puede volver a transformar en una lista si es necesario):

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

Si necesitamos mantener el orden de los elementos, ¿qué tal esto?

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

Y una solución más usando reduce y sin la 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, []) 

ACTUALIZACIÓN – Marzo, 2019

Y una tercera solución, que es buena, pero algo lenta, ya que .index es 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)] 

ACTUALIZACIÓN – Oct, 2016

Otra solución con reduce , pero esta vez sin .append que hace que sea más legible para los humanos y más fácil de entender.

 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, []) 

NOTA: Tenga en cuenta que cuanto más legibles para los humanos obtenemos, más desfavorable es la secuencia de comandos.

 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 

RESPONDIENDO COMENTARIOS

Porque @monica hizo una buena pregunta sobre “¿cómo funciona esto?”. Para todos los que tienen problemas para resolverlo. Intentaré dar una explicación más profunda sobre cómo funciona esto y qué hechicería está sucediendo aquí;)

Así que ella primero preguntó:

Intento entender por qué unique = [used.append(x) for x in mylist if x not in used] no funciona.

Bueno en realidad esta funcionando

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

El problema es que simplemente no estamos obteniendo los resultados deseados dentro de la variable unique , sino solo dentro de la variable used . Esto se debe a que durante la comprensión de la lista .append modifica la variable used y devuelve None .

Entonces, para obtener los resultados en la variable unique , y aún usar la misma lógica con .append(x) if x not in used , necesitamos mover esta llamada .append en el lado derecho de la lista de comprensión y devolver solo x En el lado izquierdo.

Pero si somos demasiado ingenuos y solo vamos con:

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

No obtendremos nada a cambio.

Nuevamente, esto se debe a que el método .append devuelve None , y esto le da a nuestra expresión lógica el siguiente aspecto:

 x not in used and None 

Esto será básicamente siempre:

  1. evalúa a False cuando se used x ,
  2. evalúa a None cuando x no está en used .

Y en ambos casos ( False / None ), esto se tratará como falsy valor falsy y, como resultado, obtendremos una lista vacía.

Pero, ¿por qué esto se evalúa como None cuando x no se used ? Alguien puede preguntar.

Bueno, es porque así es como funcionan los operadores de cortocircuitos de Python.

La expresión x and y primero evalúa x; si x es falso, su valor es devuelto; de lo contrario, se evalúa y y se devuelve el valor resultante.

Por lo tanto, cuando x no se usa (es decir, cuando es True ) , se evaluará la siguiente parte o la expresión ( used.append(x) ) y se devolverá su valor ( None ) .

Pero eso es lo que queremos para obtener los elementos únicos de una lista con duplicados, queremos .append en una nueva lista solo cuando nos encontramos con ellos por primera vez.

Así que realmente queremos evaluar used.append(x) solo cuando x no está en used , tal vez si hay una manera de convertir este valor de None en uno truthy , estaremos bien, ¿verdad?

Bueno, sí, y aquí es donde entra en juego el segundo tipo de operadores de short-circuit .

La expresión x or y primero evalúa x; Si x es verdadero, se devuelve su valor; de lo contrario, se evalúa y y se devuelve el valor resultante.

Sabemos que .append(x) siempre será falsy , por lo que si solo agregamos uno or junto a él, siempre obtendremos la siguiente parte. Por eso escribimos:

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

por lo que podemos evaluar used.append(x) y obtener True como resultado, solo cuando la primera parte de la expresión (x not in used) es True .

Se puede ver una moda similar en el segundo enfoque con el método de 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) 

donde estamos:

  1. Agregue x a l y devuelva que l cuando x no esté en l . Gracias a la sentencia or .append se evalúa y luego se devuelve l .
  2. Retorno l intacto cuando x está en l

Orden de mantenimiento:

 # 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 

La orden no importa

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

Esta es una solución simple

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

Obteniendo elementos únicos de la lista

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

Uso de lógica simple a partir de conjuntos: los conjuntos son una lista única de elementos

 mylist=list(set(mylist)) In [0]: mylist Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Usando la lógica 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] 

Usando el método pop -> pop elimina el último elemento indexado y lo muestra al usuario. vídeo

 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] 

Usando numpy

 import numpy as np np.unique(mylist) In [0]: mylist Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Referencia

conjunto – colección desordenada de elementos únicos. La lista de elementos se puede pasar al constructor del conjunto. Entonces, pase la lista con elementos duplicados, nos configuramos con elementos únicos y lo transformamos de nuevo en lista, luego obtenemos la lista con elementos únicos. No puedo decir nada sobre el rendimiento y la sobrecarga de memoria, pero espero que no sea tan importante con listas pequeñas.

 list(set(my_not_unique_list)) 

Simplemente y corto.

Si está utilizando numpy en su código (lo que podría ser una buena opción para grandes cantidades de datos), consulte 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=' 

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

Como puede ver, Numpy no solo admite datos numéricos, también son posibles matrices de cadenas. Por supuesto, el resultado es una matriz numpy, pero no importa mucho, porque todavía se comporta como una secuencia:

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

Si realmente desea recuperar una lista de python de vainilla, siempre puede llamar a la lista ().

Sin embargo, el resultado se clasifica automáticamente, como se puede ver en los fragmentos de código anteriores. Echa un vistazo a numpy único sin ordenación si se requiere un orden de lista de retención.

Lista única del mismo orden usando solo una compresión de lista.

 > 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 da el índice i elemento e como una tuple .

my_list.index devuelve el primer índice de e . Si el primer índice no es i , la iteración actual e no es la primera e en la lista.

Editar

Debo tener en cuenta que esta no es una buena manera de hacerlo, en cuanto al rendimiento. Esta es solo una manera de lograrlo usando solo una compresión de lista.

Usando la propiedad básica del diccionario de Python:

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

La salida será:

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

Lo primero, el ejemplo que dio no es una lista válida.

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

Supongamos que si está arriba es la lista de ejemplos. Luego, puede usar la siguiente receta como documento de ejemplo de itertools que puede devolver los valores únicos y conservar el orden que parezca necesario. El iterable aquí es el 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') --> ABCD # unique_everseen('ABBCcAD', str.lower) --> ABCD 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 
 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 

set puede ayudarlo a filtrar los elementos de la lista que están duplicados. Funcionará bien para los elementos str , int o tuple , pero si su lista contiene dict u otros elementos de la list , terminará con las excepciones de TypeError .

Aquí hay una solución general para preservar el orden para manejar algunos (no todos) tipos no 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 

Como beneficio adicional, Counter es una forma sencilla de obtener los valores únicos y el recuento de cada valor:

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

Además de las respuestas anteriores, que dicen que puede convertir su lista para establecer, también puede hacerlo de esta manera

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

la salida será

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

aunque no se conservará el orden.

Otra respuesta más simple podría ser (sin usar conjuntos)

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

Para obtener valores únicos de su lista, utilice el siguiente código:

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

IMPORTANTE: el enfoque anterior no funcionará si alguno de los elementos de una lista no es hashable, como en el caso de los tipos mutables , por ejemplo, list o 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 "", line 1, in  TypeError: unhashable type: 'dict' 

Eso significa que debe asegurarse de que la lista de trends siempre contenga solo elementos hashable, de lo contrario tendrá que usar un código más sofisticado:

 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 

Me sorprende que hasta ahora nadie haya dado una respuesta directa para preservar el orden:

 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 

Generará los valores para que funcione con más que solo listas, por ejemplo, unique(range(10)) . Para obtener una lista, solo llame a la list(unique(sequence)) , como esto:

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

Tiene el requisito de que cada elemento sea hashable y no solo comparable, sino que la mayoría de las cosas en Python lo es y es O (n) y no O (n ^ 2), así que funcionará bien con una lista larga.

  1. Al comienzo de su código, simplemente declare su lista de salida como vacía: output=[]
  2. En lugar de su código, puede usar este código trends=list(set(trends))

Puedes usar sets. Para ser claros, explico cuál es la diferencia entre una lista y un conjunto. los conjuntos son una colección desordenada de elementos únicos. Las listas son una colección ordenada de elementos. Asi que,

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

Pero: No use list / set para nombrar las variables. Esto causará un error: EX: en lugar de usar la lista en lugar de unicode_list en la anterior.

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

Alternativamente en Python 3.6+:

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

utilizar el conjunto para desduplicar una lista, devolver como lista

 def get_unique_list(lst): if isinstance(lst,list): return list(set(lst)) 

Set es una colección de elementos ordenados y únicos. Por lo tanto, puede usar set como se muestra a continuación para obtener una lista única:

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

Si desea obtener elementos únicos de una lista y mantener su orden original, entonces puede utilizar la estructura de datos OrderedDict de la biblioteca estándar 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 

De hecho, si está usando Python ≥ 3.6, puede usar dict simple para eso:

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

Ha sido posible después de la introducción de la representación “compacta” de los dictados. Compruébalo aquí . Aunque esto “se considera un detalle de implementación y no debe ser invocado”.

Mi solución para verificar que los contenidos sean únicos pero conservar el orden 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 

Edición: Probablemente pueda ser más eficiente usando las claves del diccionario para verificar la existencia en lugar de hacer un bucle completo de archivos para cada línea, no usaría mi solución para conjuntos grandes.

Sé que esta es una pregunta antigua, pero aquí está mi única solución: ¡herencia de clase !:

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

Luego, si desea agregar elementos de forma única a una lista, simplemente llame appendunique en una Lista única. Debido a que se hereda de una lista, básicamente actúa como una lista, por lo que puede usar funciones como índice (), etc. Y dado que devuelve verdadero o falso, puede averiguar si el agregado fue exitoso (elemento único) o falló (ya en la lista).

Para obtener una lista única de elementos de una lista, use un bucle for que agregue elementos a una lista única (luego cópielos a la lista).

Ejemplo de código de uso:

 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) 

Huellas dactilares:

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

Copiando a la lista:

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

Huellas dactilares:

 [1, 2, 3, 4] 

Para arrays largos

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

Prueba esta función, es similar a tu código pero es un rango dynamic.

 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