TransWikia.com

Remover itens de uma lista que estão em outra

Stack Overflow em Português Asked by Nebenzahl on November 13, 2021

Eu tenho duas listas com valores, e quando tento pesquisar um item de uma em outra, para ver se existe, está retornando False mesmo se sabendo que o item existe na lista pesquisada.


proc = [1,2,3,4]
fat = [3,4,5,6]


for p in proc:
  if proc[0] not in fat:
    result.append(proc[0])

print(result)

[]

Estas listas estao vindo de SELECT em um banco de dados, e contém um campo de tabelas.

O que posso estar fazendo de errado?

2 Answers

Se a ideia (confirmada nos comentários) é ter os elementos de proc que não estão em fat, então uma opção é:

proc = [1, 2, 3, 4]
fat = [3, 4, 5, 6]

result = []
for p in proc:
  if p not in fat:
    result.append(p)

print(result) # [1, 2]

Ou seja, para cada elemento de proc, verifique se ele não está em fat (e se não estiver, adicione em result).

O erro do seu código é que você estava verificando proc[0] (o primeiro elemento de proc) em todas as iterações.


Outra alternativa para o código acima é usar uma list comprehension, bem mais sucinta e pythônica:

result = [ p for p in proc if p not in fat ]

Mas tem um detalhe aí. Para cada elemento de proc, temos que verificar se o mesmo está em fat. E o operador in tem complexidade linear: ele percorre fat desde o início, até encontrar o elemento (ou percorre a lista toda, no caso do elemento não existir nela). Ou seja, este algoritmo percorre várias e várias vezes a mesma lista (o que o torna um forte candidato a ser um Shlemiel the painter’s algorithm).

Se a ordem dos elementos não é importante, e não há elementos duplicados (ou há, mas no resultado as duplicadas podem ser eliminadas), uma opção é usar set, que é uma estrutura otimizada para certas operações, como verificar se um elemento existe, entre outras.

Assim, a ideia é transformar cada lista em um set, subtraí-los (assim eu terei outro set contendo os elementos de um que não estão no outro), e no final transformo novamente em lista:

result = list(set(proc) - set(fat))

Lembrando novamente que:

  • um set não garante a ordem dos elementos, então a lista result não necessariamente terá os números na mesma ordem em que estavam na lista original (pode ser que sim, pode ser que não, então não conte com isso)
  • um set elimina valores duplicados, então se a lista proc for, por exemplo, [1, 2, 3, 4, 1], o resultado final será apenas [1, 2]

Mas se manter a ordem original dos elementos e/ou não eliminar valores duplicados forem requisitos do problema, aí não tem jeito, tem que fazer o for mesmo.


Apenas para comparar o desempenho de cada solução, fiz um pequeno teste com o módulo timeit:

import random
import timeit

# criar listas com mil números aleatórios
nums = range(10000) # números possíveis para as listas
proc = random.choices(nums, k=1000)
fat = random.choices(nums, k=1000)

n = 100 # rodar 100 vezes cada teste
r = 3 # repetir por 3 vezes (assim, repeat retorna uma lista com 3 tempos)
print(timeit.repeat("result = []nfor p in proc:n  if p not in fat:n    result.append(p)", repeat=r, number=n, globals=globals()))
print(timeit.repeat('[ p for p in proc if p not in fat ]', repeat=r, number=n, globals=globals()))
print(timeit.repeat('list(set(proc) - set(fat))', repeat=r, number=n, globals=globals()))

Claro que os tempos podem variar conforme o hardware e outro fatores, e para listas pequenas - como as que você usou - a diferença será insignificante, mas no geral, usar set se mostrou bem mais rápido. Na minha máquina os tempos foram (em segundos):

[1.4215344, 1.4107937, 1.4132282999999997]
[1.4147277999999996, 1.4120507999999994, 1.3960000999999993]
[0.015077500000000299, 0.014714099999999064, 0.015252100000001434]

Ou seja, usar set foi, em geral, cerca de 100 vezes mais rápido. No Repl.it os resultados foram similares.

Answered by hkotsubo on November 13, 2021

Pelo que entendi do seu enunciado, você está precisando encontrar os valores que são comuns às duas listas.

Se o que importar for o valor do elemento, sem levar em consideração a quantidade de ocorrências de cada elemento, podemos converter as duas listas para conjuntos, calcular a intersecção dos conjuntos e, em seguida, exibir o resultado em uma nova lista. Para isso podemos utilizar o seguinte algoritmo...

proc = [1, 2, 3, 4]
fat = [3, 4, 5, 6]
proc = set(proc)
fat = set(fat)

inter = list(proc & fat)
print(inter)

Veja o funcionamento do algoritmo no repl.it.

Agora, se você pretendo exibir os elementos em ordem crescente de valores, você pode ordenar os valores na saída. Para isso aplicamos a função sorted. Para isso basta utilizar o algoritmo...

proc = [1, 2, 3, 4]
fat = [3, 4, 5, 6]
proc = set(proc)
fat = set(fat)

inter = list(sorted(proc & fat))
print(inter)

Veja o funcionamento do algoritmo no repl.it.

Answered by Solkarped on November 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP