2012-08-05 8 views
10

Duplicar posible:
What does python intern do, and when should it be used?¿Cómo hago que Python haga que todas las cadenas idénticas usen la misma memoria?

estoy trabajando con un programa en Python que tiene para correlacionar en una matriz con millones de objetos de cadena. Descubrí que si todos provienen de la misma cadena citada, cada "cadena" adicional es solo una referencia a la primera cadena maestra. Sin embargo, si las cadenas se leen desde un archivo, y si las cadenas son todas iguales, cada una de ellas requiere una nueva asignación de memoria.

Es decir, esto tiene sobre 14meg de almacenamiento:

a = ["foo" for a in range(0,1000000)] 

Si bien esto requiere más que 65meg de almacenamiento:

a = ["foo".replace("o","1") for a in range(0,1000000)] 

Ahora puede hacer que la memoria se necesita mucho menos espacio con esto:

s = {"f11":"f11"} 
a = [s["foo".replace("o","1")] for a in range(0,1000000)] 

Pero eso parece una tontería. ¿Hay alguna forma más fácil de hacer esto?

+5

@Maulwurfn, el hecho de que la respuesta sea la misma no significa que la pregunta sea la misma. –

+0

¿por qué no almacena el valor de la operación 'replace' primero? – JBernardo

+1

¿Cómo se mide el tamaño de las listas? Si uso 'sys.getsizeof ([" foo "para un rango (0,1000000)])' obtengo el mismo tamaño que 'sys.getsizeof ([" foo ".replace (" o "," 1 ") para un rango (0,1000000)]) '- al menos en Python 3.2 –

Respuesta

13

acaba de hacer un intern(), que le dice a Python para almacenar y tomar la cadena de la memoria:

a = [intern("foo".replace("o","1")) for a in range(0,1000000)] 

Esto también se traduce en torno a 18 MB, lo mismo que en el primer ejemplo.

También tenga en cuenta el comentario a continuación, si utiliza python3. Thx @Abe Karplus

+2

Tenga en cuenta que en Python 3, 'intern' ha sido renombrado' sys.intern'. –

+1

+1 No sabía sobre 'pasante()'. –

+1

Gracias genial. Gracias. No sabía acerca de pasante. Sí, estoy usando Python3, así que tendré que usar sys.intern(). – vy32

0

puede intentar algo como esto:

strs=["this is string1","this is string2","this is string1","this is string2", 
     "this is string3","this is string4","this is string5","this is string1", 
     "this is string5"] 
new_strs=[] 
for x in strs: 
    if x in new_strs: 
     new_strs.append(new_strs[new_strs.index(x)]) #find the index of the string 
                #and instead of appending the 
               #string itself, append it's reference. 
    else: 
     new_strs.append(x) 

print [id(y) for y in new_strs] 

cadenas que son idénticos ahora tendrá la misma id()

de salida:

[18632400, 18632160, 18632400, 18632160, 18651400, 18651440, 18651360, 18632400, 18651360] 
+0

Buena idea. Desafortunadamente es un algoritmo O (n ** 2) que se volverá muy lento a medida que la lista se alarga. –

-1

Mantener un diccionario de cadenas visto debe trabajo

new_strs = [] 
str_record = {} 
for x in strs: 
    if x not in str_record: 
     str_record[x] = x 
    new_strs.append(str_record[x]) 

(no probado).

Cuestiones relacionadas