2012-08-05 8 views
10

Eventuali duplicati:
What does python intern do, and when should it be used?Come faccio a far eseguire a Python tutte le stringhe identiche usando la stessa memoria?

sto lavorando con un programma in python che deve correlare su un array con milioni di oggetti stringa. Ho scoperto che se provengono tutti dalla stessa stringa quotata, ogni "stringa" aggiuntiva è solo un riferimento alla prima stringa principale. Tuttavia se le stringhe vengono lette da un file e se le stringhe sono tutte uguali, ognuna richiede ancora una nuova allocazione di memoria.

Cioè, questo richiede circa 14meg di stoccaggio:

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

Anche se questo richiede più di 65meg di stoccaggio:

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

ora posso fare il ricordo prende molto meno spazio con questo:

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

Ma sembra sciocco. C'è un modo più semplice per farlo?

+5

@Maulwurfn, solo perché la risposta è la stessa non significa che la domanda sia la stessa. –

+0

perché non memorizzi prima il valore dell'operazione 'replace'? – JBernardo

+1

Come stai misurando la dimensione degli elenchi? Se uso 'sys.getsizeof ([" foo "per a in range (0,1000000)])) ottengo le stesse dimensioni di' sys.getsizeof (["foo" .replace ("o", "1") per a in range (0,1000000)])) - almeno in Python 3.2 –

risposta

13

basta fare un intern(), che dice Python per memorizzare e prendere la stringa dalla memoria:

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

Ciò comporta anche intorno 18MB, come nel primo esempio.

Si noti inoltre il commento seguente, se si utilizza python3. Thx @Abe Karplus

+2

Si noti che in Python 3, 'intern' è stato rinominato' sys.intern'. –

+1

+1 Non sapevo di 'intern()'. –

+1

Grazie grandi. Grazie. Non sapevo dello stagista. Sì, sto usando Python3, quindi ho bisogno di usare sys.intern(). – vy32

0

si può provare qualcosa di simile:

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] 

stringhe che sono identici avranno ora la stessa id()

uscita:

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

Bella idea. Sfortunatamente è un algoritmo O (n ** 2) che diventerà molto lento man mano che la lista si allungherà. –

-1

Mantenere un dizionario di stringhe visto dovrebbe lavoro

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

(testato.)

Problemi correlati