2012-08-05 12 views
10

Powiel możliwe:
What does python intern do, and when should it be used?Jak sprawić, aby Python powodował, że wszystkie identyczne ciągi używały tej samej pamięci?

Pracuję z programu w Pythonie, który musi korelować na tablicy z milionami obiektów smyczkowych. Odkryłem, że jeśli wszystkie pochodzą z tego samego cytowanego ciągu, każdy dodatkowy "ciąg" jest po prostu odniesieniem do pierwszego, głównego ciągu. Jednak jeśli łańcuchy są odczytywane z pliku, a wszystkie łańcuchy są równe, to każdy z nich wymaga nowego przydziału pamięci.

Oznacza to, że zajmuje to około 14meg przechowywania:

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

Choć wymaga to więcej niż 65meg przechowywania:

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

Teraz mogę uczynić pamięć wziąć dużo mniej miejsca z tym:

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

Ale to wydaje się głupie. Czy istnieje prostszy sposób na zrobienie tego?

+5

@Maulwurfn, tylko dlatego, że odpowiedź jest taka sama, nie oznacza, że ​​pytanie jest takie samo. –

+0

dlaczego nie przechowujesz najpierw wartości operacji 'replace'? – JBernardo

+1

Jak mierzysz rozmiar list? Jeśli używam 'sys.getsizeof ([" foo "dla a w zakresie (0,1000000)])' Dostaję ten sam rozmiar co 'sys.getsizeof ([" foo ".replace (" o "," 1 ") dla zakresu (0,1000000)]) '- przynajmniej w Pythonie 3.2 –

Odpowiedz

13

prostu zrobić intern(), który mówi Pythona do przechowywania i podjąć ciąg z pamięci:

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

Wynika to również około 18MB, tak samo jak w pierwszym przykładzie.

Należy również zwrócić uwagę na poniższy komentarz, jeśli używasz python3. Thx @Abe Karplus

+2

Należy zauważyć, że w Pythonie 3 zmieniono nazwę 'intern' na' sys.intern'. –

+1

+1 Nie wiedziałem o 'intern()'. –

+1

Dzięki wielkie. Dzięki. Nie wiedziałem o stażyście. Tak, używam Python3, więc będę musiał użyć sys.intern(). – vy32

0

można spróbować coś takiego:

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] 

strun, które są identyczne będą mieć taką samą id()

wyjściowe:

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

Niezły pomysł. Niestety jest to algorytm O (n ** 2), który będzie bardzo powolny, gdy lista się wydłuży. –

-1

Prowadzenie słownika widzianych strun powinna praca

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

(niesprawdzone.)

Powiązane problemy