2012-06-20 11 views
5

Buduję klasę z między innymi słownikiem z kluczami całkowitymi i wartościami listy. Dodawanie wartości do tego słownika wydaje się być jednak wąskim gardłem i zastanawiałem się, czy może być jakiś sposób na przyspieszenie mojego kodu.Python: optymalny sposób dodawania do słownika z wartościami listy

class myClass(): 

    def __init__(self): 
    self.d = defaultdict(list) 

    def addValue(self, index, value): 
    self.d[index].append(value) 

Czy to naprawdę optymalny sposób na zrobienie tego? Nie bardzo zależy mi na kolejności wartości, więc może istnieje bardziej odpowiednia struktura danych z szybszym dodatkiem. Z drugiej strony, "append" nie wydaje się być głównym problemem, ponieważ jeśli po prostu dołączę do pustej listy, kod jest o wiele szybszy. Domyślam się, że to ładowanie wcześniej zapisanej listy, która zajmuje większość czasu?


I okazało się, że problem nie leży w dict, ale na liście append (choć twierdził inaczej w moim oryginalnego postu, na który ja przepraszam). Ten problem jest spowodowany błędem w garbagerze Pythona, który jest dobrze wyjaśniony na this other question. Wyłączenie gc przed dodaniem wszystkich wartości, a następnie ponownym włączeniem, znacznie przyspiesza proces!

+2

Dodawanie elementów do listy i uzyskiwanie wartości z obiektu lub dyktowania nie zajmuje dużo czasu. Aby przyspieszyć program, należy znaleźć wąskie gardło poprzez profilowanie, a nie przez zmianę losowych fragmentów kodu. –

+0

Czy mapowanie elementów do istniejących kluczy jest znacznie szybsze niż dodawanie wartości do nowych kluczy? –

+0

Właśnie się dowiedziałem, że problem nie jest w dyktafonie, ale na liście dołączam (chociaż w moim oryginalnym poście twierdziłem inaczej, za co przepraszam). Następnie znalazłem odpowiedź na moje pytanie na http://stackoverflow.com/questions/2473783/is-there-a-way-to-circumvent-python-list-append-becoming-progressively- wolniej. Ponieważ jestem nowy na tej stronie, nie wiem, jaka jest standardowa procedura: czy powinienem usunąć mój pierwotny wpis? Lub dodać powyższe dane i odpowiedź na post? – niefpaarschoenen

Odpowiedz

0

Podsumowując, mogę powiedzieć, że mój kod w pierwotnym pytaniu jest szybszy lub tak szybki, jak wszystkie inne sugestie.

2

Porównaj to do tego:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    self.d.setdefault(index, []).append(value) 
+1

Z ciekawości, dlaczego jest to szybsze? Pomyślałem, że "defaultdict" robi coś bardzo podobnego za kulisami. –

+1

Po krótkim teście dowiedziałem się, że nie jest to szybsze. Po prostu lubię to lepiej. – eumiro

+0

Myślę, że faktycznie robi to samo za kulisami; czasy są podobne w każdym przypadku ... Wolę jednak defaultdict, ponieważ generalnie trzeba pisać mniej. – niefpaarschoenen

1

Mówią "Lepiej poprosić o wybaczenie niż o pozwolenie.". Teraz nie pytasz o pozwolenie osobiście, ale myślałem, że może to zrobić, i to właśnie spowalnia działanie.

try to:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    try: 
     self.d[index].append(value) 
    except KeyError: 
     self.d[index] = [value] 

ten próbuje uzyskać dostęp do klucza index w słowniku, jeśli nie istnieje, to podnieść KeyError, i działają na nim.

Czy to jest szybsze?

+0

Próbowałem porównać twój kod i kod z pytaniem (używając [timeit] (http://docs.python.org/library/timeit.html)). Użyłem tego testu: 'my = myClass() my.addValue (3," ab ") my.addValue (3," cd ") my.addValue (4," ef ") my.addValue (4, "gh") 'A oryginalny kod jest szybszy! Na moim komputerze: 24,66 usec dla twojego kodu i 18.10 usec dla kodu z pytania. Wygląda na to, że to podejście nie jest odpowiedzią. – stalk

+1

Wygląda na to, że masz najszybsze rozwiązanie od tego czasu :) – jadkik94

Powiązane problemy