a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a & b deve ser considerado igual, porque eles têm exatamente os mesmos elementos, apenas em ordem diferente.
O problema é que minhas listas reais consistem em objetos (minhas instâncias de classe), não em números inteiros.
python
algorithm
list
comparison
johndir
fonte
fonte
len()
s primeiro.Respostas:
O (n) : O método Counter () é melhor (se seus objetos são hasháveis):
O (n log n) : O método classificado () é o próximo melhor (se seus objetos podem ser pedidos):
O (n * n) : se os objetos não forem hasháveis nem ordenáveis, você poderá usar a igualdade:
fonte
sorted()
, reconhecidamente não sabendoCounter
. O entrevistador insistiu que havia um método mais eficiente e claramente eu deixei um espaço em branco. Após testes extensivos no python 3 com otimeit
módulo, a classificação é lançada consistentemente mais rapidamente nas listas de números inteiros. Nas listas de 1 mil itens, cerca de 1,5% mais devagar e nas listas curtas, 10 itens, 7,5% mais lentos. Pensamentos?python3.6 -m timeit -s 'from collections import Counter' -s 'from random import shuffle' -s 't=list(range(100)) * 5' -s 'shuffle(t)' -s 'u=t[:]' -s 'shuffle(u)' 'Counter(t)==Counter(u)'
sorted vs counter
.. Estou muito curioso para saber o que está acontecendo aqui.Você pode classificar os dois:
Uma classificação de contagem também pode ser mais eficiente (mas exige que o objeto seja lavável).
fonte
__hash__
, mas isso pode ser impossível para coleções.sorted([0, 1j])
Se você sabe que os itens são sempre laváveis, você pode usar um
Counter()
que é O (n)Se você sabe que os itens são sempre ordenáveis, você pode usar o
sorted()
que é O (n log n)No caso geral, você não pode confiar em poder classificar ou possui os elementos; portanto, você precisa de um fallback como esse, que infelizmente é O (n ^ 2)
fonte
A melhor maneira de fazer isso é ordenando as listas e comparando-as. (O uso
Counter
não funcionará com objetos que não são laváveis.) Isso é simples para números inteiros:Fica um pouco mais complicado com objetos arbitrários. Se você se importa com a identidade do objeto, ou seja, se os mesmos objetos estão nas duas listas, você pode usar a
id()
função como chave de classificação.(No Python 2.x, você realmente não precisa do
key=
parâmetro, porque é possível comparar qualquer objeto a qualquer objeto. A ordem é arbitrária, mas estável, portanto funciona bem para esse propósito; não importa em que ordem os objetos estejam. No entanto, no Python 3, comparar objetos de tipos diferentes não é permitido em muitas circunstâncias - por exemplo, você não pode comparar cadeias de caracteres com números inteiros - portanto, se você tiver objetos de vários tipos, melhor usar explicitamente o ID do objeto.)Se você deseja comparar os objetos da lista por valor, por outro lado, primeiro precisa definir o que "valor" significa para os objetos. Então você precisará de alguma maneira de fornecer isso como uma chave (e para o Python 3, como um tipo consistente). Uma maneira potencial que funcionaria para muitos objetos arbitrários é classificar por eles
repr()
. Obviamente, isso poderia desperdiçar muito tempo extra erepr()
seqüências de construção de memória para listas grandes e assim por diante.Se os objetos são todos do seu próprio tipo, você pode defini
__lt__()
-los para que o objeto saiba como se comparar a outros. Então você pode apenas classificá-los e não se preocupar com okey=
parâmetro. Claro que você também pode definir__hash__()
e usarCounter
, o que será mais rápido.fonte
https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
assertCountEqual (primeiro, segundo, msg = nenhum)
Teste essa sequência primeiro contém os mesmos elementos que o segundo, independentemente de sua ordem. Quando não o fizerem, uma mensagem de erro listando as diferenças entre as seqüências será gerada.
Elementos duplicados não são ignorados ao comparar o primeiro e o segundo. Ele verifica se cada elemento tem a mesma contagem nas duas seqüências. Equivalente a: assertEqual (Contador (lista (primeiro)), Contador (lista (segundo))), mas também trabalha com seqüências de objetos laváveis.
Novo na versão 3.2.
ou no 2.7: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
fonte
Se a lista contiver itens que não são laváveis (como uma lista de objetos), você poderá usar a Classe de Contador e a função id (), como:
fonte
Espero que o trecho de código abaixo possa funcionar no seu caso: -
Isso irá garantir que todos os elementos em ambas as listas
a
eb
são os mesmos, independentemente de se eles estão em mesma ordem ou não.Para uma melhor compreensão, consulte a minha resposta nesta pergunta
fonte
Se a comparação for realizada em um contexto de teste, use
assertCountEqual(a, b)
(py>=3.2
) eassertItemsEqual(a, b)
(2.7<=py<3.2
).Também funciona em seqüências de objetos unhashable.
fonte
Deixe as listas a, b
Não há necessidade de torná-los laváveis ou classificá-los.
fonte
a
suportespop
(é mutável) eindex
(é uma sequência). O de Raymond não assume nenhum, enquanto o gnibbler assume apenas uma sequência.O uso do
unittest
módulo oferece uma abordagem limpa e padrão.fonte