2009-08-19 3 views
16

Umieszczę około 4 miliony różnych kluczy w słowniku Python. Utworzenie tego słownika zajmuje około 15 minut i zajmuje około 4 GB pamięci na moim komputerze. Po pełnym utworzeniu słownika, zapytanie do słownika jest szybkie.Jak ustawić rozmiar początkowy słownika w Pythonie?

Podejrzewam, że tworzenie słownika jest bardzo zasobochłonne, ponieważ słownik jest często odnawiany (ponieważ rośnie ogromnie). Czy jest możliwe utworzenie słownika w Pythonie z pewnym początkowym rozmiarem lub numerem wiadra?

Mój słownik wskazuje liczbę na obiekt.

class MyObject(object): 
    def __init__(self): 
    # some fields... 

d = {} 
d[i] = MyObject() # 4M times on different key... 
+0

Bardzo podobne do http://stackoverflow.com/questions/311775/python-create-a-list-dict-with-initial-capacity –

+0

Czy możesz nam podać źródło/format twoich kluczy, abyśmy mogli poprawić anwsers? –

+0

klucz to numer – tkokoszka

Odpowiedz

24

Przy problemach z wydajnością zawsze najlepiej mierzyć. Oto kilka czasy:

d = {} 
for i in xrange(4000000): 
    d[i] = None 
# 722ms 

d = dict(itertools.izip(xrange(4000000), itertools.repeat(None))) 
# 634ms 

dict.fromkeys(xrange(4000000)) 
# 558ms 

s = set(xrange(4000000)) 
dict.fromkeys(s) 
# Not including set construction 353ms 

Ostatnia opcja nie robi żadnej zmiany rozmiaru, to po prostu kopiuje hashe z zestawu i zwiększa referencje. Jak widać, zmiana rozmiaru nie zajmuje dużo czasu. Prawdopodobnie tworzenie obiektów jest wolne.

+0

Nie ma znaczenia, jak zainicjować słownik, wypełnianie go danymi zajmuje zawsze dużo czasu. Wygląda na to, że cały czas przeznaczasz na tworzenie obiektów. Dzięki! – tkokoszka

4

Można spróbować oddzielić kluczowanie hasłem od wypełnienia treści za pomocą metody klasy dict.fromkeys. Stworzy on dict znanego rozmiaru z wszystkimi wartościami domyślnymi do None lub wybraną wartością. Potem możesz go powtórzyć, aby wypełnić wartości. Pomoże ci to w czasie rzeczywistym mieszaniu wszystkich kluczy. Nie wiem, czy byłbyś w stanie znacznie zwiększyć prędkość.

2

Jeśli Twoje dane osobowe muszą/mogą być przechowywane na dysku może można przechowywać swoje dane teleadresowe w BSDDB database lub użyj Cpickle załadować/zapisać dictionnary

5

Jeśli znasz C, można spojrzeć na dictobject.c i the Notes on Optimizing Dictionaries . Tam można zauważyć parametr PyDict_MINSIZE:

PyDict_MINSIZE. Obecnie ustawione na 8.

Ten parametr jest zdefiniowany w dictobject.h. Więc możesz może zmienić go podczas kompilowania Pythona, ale to prawdopodobnie jest zły pomysł.

8

Próbowałem:

a = dict.fromkeys((range(4000000))) 

Tworzy słownik z 4 000 000 wpisów w około 3 sekundy. Następnie ustawienia są naprawdę szybkie. Domyślam się, że dict.fromkey to zdecydowanie droga.

+4

+1 za wzmiankę o dict.fromkeys(). Jednak używanie zakresu() do określania kluczy oznacza, że ​​kończy się dyktowaniem kluczy sekwencyjnych. Jeśli to konieczne, dlaczego nie skorzystać z listy?a = [Brak] * 4000000 –

+1

To nie było bezpośrednie rozwiązanie, tylko demonstracja, której można użyć od kluczy do wstępnego wygenerowania dyktatu w bardzo krótkim czasie. –

+1

Zgodnie z punktem @ShawnChin podnosi, co jeśli nie chcesz numery 1 ... 4M jako klucze? Lub w bardziej ogólnych kategoriach, co jeśli nie znasz kluczy z góry, ale wiesz, że są w milionach? – posdef

1

Czy inicjalizujesz wszystkie klucze za pomocą nowych "pustych" instancji tego samego typu? Czy nie jest możliwe zapisanie defaultdict lub coś, co stworzy obiekt, gdy będzie on dostępny?