unicos - python quitar duplicados
Obtener valores Ășnicos de una lista en python (30)
- Al comienzo de su código, simplemente declare su lista de salida como vacía:
output=[]
- En lugar de su código, puede usar este código
trends=list(set(trends))
Esta pregunta ya tiene una respuesta aquí:
- Eliminando duplicados en listas 43 respuestas
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?
¿De qué tipo es tu variable de salida?
Los sets Python son lo que necesitas. Declare la salida de esta manera:
output = set([]) # initialize an empty set
y está listo para ir agregando elementos con output.add(elem)
y asegúrese de que sean únicos.
Advertencia: los conjuntos NO conservan el orden original de la lista.
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 el orden no será preservado.
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'']
Como beneficio adicional, Counter
es una forma sencilla de obtener los valores únicos y el recuento para cada valor:
from collections import Counter
l = [u''nowplaying'', u''PBS'', u''PBS'', u''nowplaying'', u''job'', u''debate'', u''thenandnow'']
c = Counter(l)
El ejemplo que proporcionó no corresponde a las listas en Python. Se asemeja a un dict anidado, 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''])
Esta es una solución simple
list=[u''nowplaying'', u''PBS'', u''PBS'', u''nowplaying'', u''job'', u''debate'', u''thenandnow'']
list=set(list)
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. Esto es solo una manera de lograrlo usando solo una compresión de lista.
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'') --> 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
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.
Mediante el uso de 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''])
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.
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. video
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]
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))
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)]
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 mutable tipos mutable , 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 "<stdin>", line 1, in <module>
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
Para ser consistente con el tipo que usaría:
mylist = list(set(mylist))
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 .
Pruebe esta función, es similar a su código pero es un rango dinámico.
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
Puedes usar sets. Solo 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. Causará el 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
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 index (), etc. Y dado que devuelve verdadero o falso, puede averiguar si el agregado fue exitoso (elemento único) o falló (ya en la lista). 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]
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 de 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 here . Aunque esto "se considera un detalle de implementación y no debe ser invocado".
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=''<U10'')
( 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 vainilla pitón, 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 unique sin ordenación si se requiere un orden de lista de retención.
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 - 1 de octubre de 2016
Otra solución con reduce
, pero esta vez sin .append
que hace que sea más legible 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 legible 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.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
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
al 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:
- evalúa a
False
cuando seused
x
, - evalúa a
None
cuandox
no está enused
.
Y en ambos casos ( False
/ None
), esto será tratado 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 works operadores de short-circuit 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:
- Agregue
x
al
y devuelva quel
cuandox
no está enl
. Gracias a la sentenciaor
.append
se evalúa y luego se devuelvel
. - Devuelve
l
intacto cuandox
está enl
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 la transformamos nuevamente a la 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.
utilizar el conjunto para desduplicar una lista, devolver como lista
def get_unique_list(lst):
if isinstance(lst,list):
return list(set(lst))
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
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
def setlist(lst=[]):
return list(set(lst))
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'']