Elimina e extrae elementos duplicados dunha lista (matriz) en Python

Negocios

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)
  • 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.

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'
Copied title and URL