Tengo este requisito único que puede explicarse con este código. Este es un código de trabajo pero no es eficiente en memoria.
data = [[
"A 5408599",
"B 8126880",
"A 2003529",
],
[
"C 9925336",
"C 3705674",
"A 823678571",
"C 3205170186",
],
[
"C 9772980",
"B 8960327",
"C 4185139021",
"D 1226285245",
"C 2523866271",
"D 2940954504",
"D 5083193",
]]
temp_dict = {
item: index for index, sublist in enumerate(data)
for item in sublist
}
print(data[temp_dict["A 2003529"]])
out: ['A 5408599', 'B 8126880', 'A 2003529']
En resumen, quiero que cada elemento de la sublista sea indexable y debería devolver la sublista.
El método anterior funciona pero requiere mucha memoria cuando los datos son grandes. ¿Hay alguna forma mejor para la memoria y la CPU? Los datos se almacenan como un archivo JSON.
Editar Probé las respuestas para el escenario de caso de uso más grande posible (1000 sublistas, 100 elementos en cada sublista, 1 millón de consultas) y aquí están los resultados (media de 10 ejecuciones):
Method, Time (seconds), Extra Memory used
my, 0.637 40 Mb
deceze, 0.63 40 Mb
James, 0.78 200 kb
Pant, > 300 0 kb
mcsoini, forever 0 kb
{item: sublist for sublist in data for item in sublist}
¿podría ser un poco más eficiente y directo ...?Respuestas:
Realmente se encuentra en un espacio de compensación entre el tiempo / memoria que lleva generar el diccionario y el tiempo que lleva escanear todos los datos para obtener un método sobre la marcha.
Si desea un método con poca memoria, puede usar una función que busque el valor en cada sublista. El uso de un generador obtendrá resultados iniciales más rápido para el usuario, pero para grandes conjuntos de datos, esto será lento entre los retornos.
Como se mencionó en los comentarios, construir una tabla hash basada solo en la primera letra o los primeros 2 o 3 caracteres podría ser un buen lugar para comenzar. Esto le permitirá crear una lista de sublistas candidatas, luego escanearlas para ver si el valor está en la sublista.
La
quick_hash
creación de este código llevará algún tiempo, ya que está escaneando toda su estructura de datos. Sin embargo, la huella de memoria será mucho más pequeña. Su parámetro principal para ajustar el rendimiento essize
. Un tamaño más pequeño tendrá una huella de memoria más pequeña, pero llevará más tiempo cuando se ejecutefind_list_by_hash
porque su grupo de candidatos será más grande. Puede hacer algunas pruebas para ver cuálsize
debería ser el derecho para sus datos. Solo tenga en cuenta que todos sus valores son al menos tan largos como sea posiblesize
.fuente
Puedes probar algo como esto:
No es necesario hacer una estructura de mapeo.
fuente
prueba esto, usando pandas
Esto parece una solución simple, incluso si sus datos crecen, esto lo manejará de manera eficiente
fuente
df
: es considerablemente más grande que la listadata
(> x12) y el dicttemp_dict
(~ x2) para los datos de ejemplo que se da - no es exactamente la memoria eficientes diríapandas
maneja este problema de manera más eficiente que la funcionalidad incorporada de Python.pandas
si se puede hacer usandostdlib
. ¿Solo porque parece elegante?No estoy completamente seguro de cómo se comportaría esto para datos de cantidades más grandes, pero podría intentar algo en la línea de:
Editar: no parece ser beneficioso en términos de tiempo, basado en una prueba rápida con algunos datos falsos a mayor escala.
fuente