a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a & b deben considerarse iguales, porque tienen exactamente los mismos elementos, solo que en un orden diferente.
La cuestión es que mis listas reales consistirán en objetos (mis instancias de clase), no enteros.
python
algorithm
list
comparison
johndir
fuente
fuente
len()
s primero.Respuestas:
O (n) : el método Counter () es el mejor (si sus objetos son hashaable):
O (n log n) : el método sorted () es el siguiente mejor (si sus objetos son ordenables):
O (n * n) : si los objetos no son hashables ni pueden pedirse, puede usar la igualdad:
fuente
sorted()
, sin saberloCounter
. El entrevistador insistió en que había un método más eficiente y claramente hice un espacio en blanco. Después de extensas pruebas en Python 3 con eltimeit
módulo, ordenado consistentemente sale más rápido en las listas de enteros. En listas de, 1k elementos, aproximadamente 1.5% más lento y en listas cortas, 10 elementos, 7.5% más lento. Pensamientos?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
. Tengo mucha curiosidad sobre lo que está pasando aquí.Puedes ordenar ambos:
Una ordenación de conteo también podría ser más eficiente (pero requiere que el objeto sea hashable).
fuente
__hash__
, pero eso podría ser imposible para las colecciones.sorted([0, 1j])
Si sabe que los elementos son siempre utilizables, puede usar uno
Counter()
que sea O (n)Si sabe que los elementos siempre se pueden ordenar, puede usar
sorted()
cuál es O (n log n)En el caso general, no puede confiar en poder ordenar o tener los elementos, por lo que necesita un respaldo como este, que desafortunadamente es O (n ^ 2)
fuente
La mejor manera de hacerlo es ordenar las listas y compararlas. (El uso
Counter
no funcionará con objetos que no sean hashaable). Esto es sencillo para los enteros:Se vuelve un poco más complicado con objetos arbitrarios. Si le importa la identidad del objeto, es decir, si los mismos objetos están en ambas listas, puede usar la
id()
función como la clave de clasificación.(En Python 2.x en realidad no necesita el
key=
parámetro, porque puede comparar cualquier objeto con cualquier objeto. El orden es arbitrario pero estable, por lo que funciona bien para este propósito; no importa el orden de los objetos) en, solo que el orden es el mismo para ambas listas. En Python 3, sin embargo, la comparación de objetos de diferentes tipos no está permitida en muchas circunstancias, por ejemplo, no puede comparar cadenas con enteros, por lo que si tendrá objetos de varios tipos, lo mejor es usar explícitamente la ID del objeto).Si desea comparar los objetos en la lista por valor, por otro lado, primero debe definir qué significa "valor" para los objetos. Entonces necesitará alguna forma de proporcionar eso como una clave (y para Python 3, como un tipo consistente). Una forma potencial que funcionaría para muchos objetos arbitrarios es ordenarlos por ellos
repr()
. Por supuesto, esto podría desperdiciar mucho tiempo extra y crearrepr()
cadenas de memoria para listas grandes, etc.Si los objetos son todos de su propio tipo, puede definirlos
__lt__()
para que el objeto sepa cómo compararse con los demás. Luego puede ordenarlos y no preocuparse por elkey=
parámetro. Por supuesto, también podría definir__hash__()
y usarCounter
, lo que será más rápido.fuente
https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
ClaimCountEqual (primero, segundo, msg = Ninguno)
Pruebe que la secuencia primero contiene los mismos elementos que la segunda, independientemente de su orden. Cuando no lo hacen, se generará un mensaje de error que enumera las diferencias entre las secuencias.
Los elementos duplicados no se ignoran al comparar primero y segundo. Verifica si cada elemento tiene el mismo recuento en ambas secuencias. Equivalente a: afirmarEqual (Counter (list (first)), Counter (list (second))) pero también funciona con secuencias de objetos no compartibles.
Nuevo en la versión 3.2.
o en 2.7: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
fuente
Si la lista contiene elementos que no se pueden compartir (como una lista de objetos), es posible que pueda usar la clase Counter y la función id () como:
fuente
Espero que el siguiente código funcione en su caso:
Esto asegurará que todos los elementos en las listas
a
yb
sean iguales, independientemente de si están en el mismo orden o no.Para una mejor comprensión, consulte mi respuesta en esta pregunta
fuente
Si la comparación se va a realizar en un contexto de prueba, use
assertCountEqual(a, b)
(py>=3.2
) yassertItemsEqual(a, b)
(2.7<=py<3.2
).Funciona también en secuencias de objetos no compartibles.
fuente
Deje a, b listas
No es necesario hacerlos hashaable o ordenarlos.
fuente
a
apoyospop
(es mutable) yindex
(es una secuencia). Raymond no asume nada mientras que gnibbler asume solo una secuencia.El uso del
unittest
módulo le brinda un enfoque limpio y estándar.fuente