Preciso comparar duas listas para criar uma nova lista de elementos específicos encontrados em uma lista, mas não na outra. Por exemplo:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
Desejo percorrer a lista_1 e acrescentar à main_list todos os elementos da lista_2 que não foram encontrados na lista_1.
O resultado deve ser:
main_list=["f", "m"]
Como posso fazer isso com python?
list_2
que não aparecem em nenhum lugarlist_1
ou elementoslist_2
que não estão presentes no mesmo índice emlist_1
?Respostas:
TL; DR:
SOLUÇÃO (1)
SOLUÇÃO (2) Você deseja uma lista ordenada
EXPLICAÇÕES:
(1) Você pode usar NumPy do
setdiff1d
(array1
,array2
,assume_unique
=False
).assume_unique
pergunta ao usuário se as matrizes já são únicas.Se
False
, então os elementos exclusivos são determinados primeiro.Se
True
, a função assumirá que os elementos já são exclusivos E a função ignorará a determinação dos elementos exclusivos.Isso resulta os valores exclusivos em
array1
que não são nosarray2
.assume_unique
éFalse
por padrão.Se você está preocupado com os elementos exclusivos (com base na resposta de Chinny84 ), basta usar (onde
assume_unique=False
=> o valor padrão):(2) Para quem deseja que as respostas sejam classificadas, criei uma função personalizada:
Para obter a resposta, execute:
NOTAS LATERAIS:
(a) A solução 2 (função personalizada
setdiff_sorted
) retorna uma lista (comparada a uma matriz na solução 1).(b) Se você não tem certeza se os elementos são únicos, use a configuração padrão de NumPy
setdiff1d
nas soluções A e B. O que pode ser um exemplo de complicação? Veja a nota (c).(c) As coisas serão diferentes se uma das duas listas não for única.
Diga
list_2
não é único:list2 = ["a", "f", "c", "m", "m"]
. Manterlist1
como está:list_1 = ["a", "b", "c", "d", "e"]
configurando o valor padrão dos
assume_unique
rendimentos["f", "m"]
(em ambas as soluções). No entanto, se você definirassume_unique=True
, as duas soluções dão["f", "m", "m"]
. Por quê? Isso ocorre porque o usuário ASSUME que os elementos são únicos). Por isso, é melhor manterassume_unique
ao seu valor padrão. Observe que as duas respostas estão classificadas.Pitãoentorpecido
fonte
Você pode usar conjuntos:
Resultado:
De acordo com o comentário do @JonClements, aqui está uma versão mais organizada:
fonte
unique
elementos, mas e se tivermos vários,m's
por exemplo, isso não seria suficiente.list(set(list_2).difference(list_1))
que evita aset
conversão explícita ...Não sei por que as explicações acima são tão complicadas quando você tem métodos nativos disponíveis:
fonte
Use uma compreensão de lista como esta:
Resultado:
Editar:
Como mencionado nos comentários abaixo, com grandes listas, o acima não é a solução ideal. Nesse caso, uma opção melhor seria a conversão
list_1
para umaset
primeira:fonte
list_1
, você iria querer preconvert a umset
/frozenset
, por exemploset_1 = frozenset(list_1)
, em seguidamain_list = [item for item in list_2 if item not in set_1]
, reduzindo o tempo de verificação deO(n)
por item de (aproximadamente)O(1)
.enumerate()
para isso:[index for (index, item) in enumerate(list_2) if item not in list_1]
Se você deseja uma solução de uma linha (ignorando importações) que requer apenas
O(max(n, m))
trabalho para entradas de comprimenton
em
, nãoO(n * m)
trabalho, você pode fazê-lo com oitertools
módulo :Isso tira proveito das funções funcionais que utilizam uma função de retorno de chamada na construção, permitindo que ele crie o retorno de chamada uma vez e reutilize-o para cada elemento sem precisar armazená-lo em algum lugar (porque o
filterfalse
armazena internamente); compreensões de lista e expressões geradoras podem fazer isso, mas é feio. †Isso obtém os mesmos resultados em uma única linha que:
com a velocidade de:
Obviamente, se as comparações pretendem ser posicionais, então:
deve produzir:
(como o valor in
list_2
tem uma correspondência no mesmo índice emlist_1
), você deve definitivamente seguir a resposta de Patrick , que não envolvelist
s ou s temporáriosset
(mesmo comset
s sendo mais ou menosO(1)
, eles têm um fator "constante" mais alto por verificação do que simples verificações de igualdade ) e envolveO(min(n, m))
trabalho, menos do que qualquer outra resposta e, se o seu problema for sensível à posição, é a única solução correta quando os elementos correspondentes aparecerem em desvios incompatíveis.†: A maneira de fazer o mesmo com a compreensão de uma lista como uma linha seria abusar do loop aninhado para criar e armazenar em cache valores no loop "mais externo", por exemplo:
que também oferece um benefício de desempenho menor no Python 3 (porque agora
set_1
é escopo localmente no código de compreensão, em vez de ser pesquisado no escopo aninhado de cada verificação; no Python 2 isso não importa, porque o Python 2 não usa fechamentos para compreensão da lista; eles operam no mesmo escopo em que são usados).fonte
resultado:
fonte
list_1
for grande elist_2
for de tamanho não trivial, pois envolvelen(list_2)
O(n)
varreduras delist_1
, tornando-aO(n * m)
(onden
em
são os comprimentos delist_2
e,list_1
respectivamente). Se você converterlist_1
a umset
/frozenset
na frente, o contém cheques pode ser feito emO(1)
, tornando o trabalho totalO(n)
da duração dolist_2
(tecnicamente,O(max(n, m))
, desde que você façaO(m)
o trabalho para tornar aset
).Eu faria
zip
as listas juntas para compará-las elemento a elemento.fonte
list
s com um único novolist
sendo construído, sem temporários adicionais , sem verificações caras de contenção, etc. #Eu usei dois métodos e achei um método útil sobre outro. Aqui está a minha resposta:
Meus dados de entrada:
Método1:
np.setdiff1d
Eu gosto dessa abordagem em detrimento de outras, porque preserva a posiçãoMétodo2: Embora dê a mesma resposta que no Método1, mas perturbe a ordem
O Method1
np.setdiff1d
atende perfeitamente aos meus requisitos. Esta resposta para informações.fonte
Se o número de ocorrências deve ser levado em consideração, você provavelmente precisará usar algo como
collections.Counter
:Como prometido, isso também pode lidar com diferentes números de ocorrências como "diferença":
fonte
No ser1 remova os itens presentes no ser2.
Entrada
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Solução
ser1 [~ ser1.isin (ser2)]
fonte