Esta sección describe como xerar unha nova lista en Python eliminando ou extraendo elementos duplicados dunha lista (matriz).
Aquí descríbense os seguintes detalles.
- Elimina os elementos duplicados e xera novas fichas
- Non conserves a orde da listaxe orixinal:
set()
- Conserva a orde da listaxe orixinal:
dict.fromkeys()
,sorted()
- Matriz bidimensional (lista de listas)
- Non conserves a orde da listaxe orixinal:
- Extrae elementos duplicados e xera unha nova lista
- Non conserves a orde da listaxe orixinal
- Conserva a orde da listaxe orixinal
- Matriz bidimensional (lista de listas)
O mesmo concepto pódese aplicar a tuplas en lugar de listas.
Consulta o seguinte artigo para
- Se queres determinar se unha lista ou tupla ten elementos duplicados
- Se queres extraer elementos que son comúns ou non entre varias listas en lugar dunha única lista
Teña en conta que as listas poden almacenar diferentes tipos de datos e son estrictamente diferentes das matrices. Se quere manexar matrices en procesos que requiren tamaño de memoria e enderezos de memoria ou procesamento numérico de grandes datos, use array (biblioteca estándar) ou NumPy.
Elimina os elementos duplicados e xera novas fichas
Non conserves a orde da listaxe orixinal:set()
Se non hai necesidade de preservar a orde da lista orixinal, use set(), que xera un conxunto de tipos de conxunto.
O tipo de conxunto é un tipo de datos que non ten elementos duplicados. Cando se pasa unha lista ou outro tipo de datos a set(), os valores duplicados ignóranse e devólvese un obxecto de tipo set no que só os valores únicos son elementos.
Se queres facelo unha tupla, usa tuple().
l = [3, 3, 2, 1, 5, 1, 4, 2, 3]
print(set(l))
# {1, 2, 3, 4, 5}
print(list(set(l)))
# [1, 2, 3, 4, 5]
Por suposto, tamén se pode deixar como configurado. Consulte o seguinte artigo para obter máis información sobre o conxunto de tipos de conxunto.
Conserva a orde da listaxe orixinal:dict.fromkeys(),sorted()
Se queres conservar a orde da lista orixinal, utiliza o método de clase fromkeys() do tipo dicionario ou a función integrada sorted().
dict.fromkeys() crea un novo obxecto dicionario cuxas claves son listas, tuplas, etc. especificadas nos argumentos. Se se omite o segundo argumento, o valor é Ningún.
Dado que as claves do dicionario non teñen elementos duplicados, os valores duplicados ignóranse como en set(). Ademais, pódese pasar un obxecto dicionario como argumento a list() para obter unha lista cuxos elementos sexan claves de dicionario.
print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}
print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]
Desde Python 3.7 (CPython é 3.6) garantiuse que dict.fromkeys() conserva a orde da secuencia de argumentos. As versións anteriores usan a función integrada sorted() do seguinte xeito.
Especifique o método de tupla de lista index() para a clave de argumento de sorted, que devolve unha lista ordenada de elementos.
index() é un método que devolve o índice do valor (o número do elemento da lista), que se pode especificar como clave de sorted() para ordenar a lista en función da orde da lista orixinal. A clave do argumento especifícase como un obxecto invocable, polo que non escriba ().
print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]
Matriz bidimensional (lista de listas)
Para matrices bidimensionais (listas de listas), o método que usa set() ou dict.fromkeys() dá como resultado un TypeError.
l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
# l_2d_unique = list(set(l_2d))
# TypeError: unhashable type: 'list'
# l_2d_unique_order = dict.fromkeys(l_2d)
# TypeError: unhashable type: 'list'
Isto débese a que os obxectos non hashable, como as listas, non poden ser elementos de tipo conxunto ou claves de tipo dict.
Define as seguintes funcións A orde da lista orixinal consérvase e funciona para listas unidimensionais e tuplas.
def get_unique_list(seq):
seen = []
return [x for x in seq if x not in seen and not seen.append(x)]
print(get_unique_list(l_2d))
# [[1, 1], [0, 1], [0, 0], [1, 0]]
print(get_unique_list(l))
# [3, 2, 1, 5, 4]
Utilízase a notación de comprensión de listas.
- RELACIONADO:Como usar as listas de comprensión de Python
Aquí, usamos o seguinte
- Se X en “X e Y” é falso na avaliación de curtocircuítos do operador e, entón Y non se avalía (non se executa).
- O método append() devolve Ningún.
Se os elementos da lista orixinal seq non existen no seen, entón e despois avalíanse.
seen.append(x) execútase e o elemento engádese a seen.
Dado que o método append() devolve None e None é Falso, non se ve.append(x) avalíase como True.
A expresión condicional na notación de comprensión da lista pasa a ser verdadeira e engádese como elemento da lista xerada final.
Se os elementos da lista orixinal seq están presentes en seen, entón x not in seen é Falso e a expresión condicional para a expresión de comprensión da lista é False.
Polo tanto, non se engaden como elementos da lista xerada final.
Outro método é establecer o eixe do argumento na función de NumPy np.unique(), aínda que o resultado será ordenado.
Extrae elementos duplicados e xera unha nova lista
Non conserves a orde da listaxe orixinal
Para extraer só elementos duplicados da lista orixinal, use collections.Counter().
Devolve un collections.Counter (unha subclase de dicionario) cos elementos como claves e o número de elementos como valores.
import collections
l = [3, 3, 2, 1, 5, 1, 4, 2, 3]
print(collections.Counter(l))
# Counter({3: 3, 2: 2, 1: 2, 5: 1, 4: 1})
Dado que é unha subclase de dicionario, items() pódese usar para recuperar claves e valores. É suficiente extraer claves cuxo número sexa dous ou máis.
print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]
Conserva a orde da listaxe orixinal
Como se mostra no exemplo anterior, desde Python 3.7, as claves das coleccións. Counter conservan a orde da lista orixinal e así por diante.
Nas versións anteriores, ordenar con sorted() é suficiente, así como eliminar elementos duplicados.
print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]
Se desexa extraer duplicados tal e como son, simplemente deixe os elementos da lista orixinal cun número de dous ou máis. Tamén se conserva a orde.
cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]
Matriz bidimensional (lista de listas)
Para matrices bidimensionais (listas de listas), as seguintes funcións son posibles cando non se conserva a orde da lista orixinal e cando se conserva, respectivamente. Tamén funciona para listas e tuplas unidimensionais.
l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
def get_duplicate_list(seq):
seen = []
return [x for x in seq if not seen.append(x) and seen.count(x) == 2]
def get_duplicate_list_order(seq):
seen = []
return [x for x in seq if seq.count(x) > 1 and not seen.append(x) and seen.count(x) == 1]
print(get_duplicate_list(l_2d))
# [[0, 1], [1, 1]]
print(get_duplicate_list_order(l_2d))
# [[1, 1], [0, 1]]
print(get_duplicate_list(l))
# [3, 1, 2]
print(get_duplicate_list_order(l))
# [3, 2, 1]
Se queres extraer con duplicados, deixa os elementos da lista orixinal cun reconto de dous ou máis.
print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]
Teña en conta que dado que a complexidade computacional de count() é O(n), a función mostrada arriba que executa repetidamente count() é moi ineficiente. Pode haber un xeito máis intelixente.
Counter é unha subclase do dicionario, polo que se pasas unha lista ou tupla cuxos elementos son listas ou outros obxectos non hashable a coleccións. Counter(), producirase un erro e non poderás usalo.
# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'