2014-04-05 18 views
9

Znalazłem rozwiązanie, ale jest to bardzo powolny:Jak podzielić słownika na wiele słowników szybkich

def chunks(self,data, SIZE=10000): 
    for i in xrange(0, len(data), SIZE): 
     yield dict(data.items()[i:i+SIZE]) 

Czy macie jakieś pomysły bez użycia zewnętrznych modułów (numpy itp)

+5

Nie wywoływać "przedmiotów". Tworzysz nową listę wszystkich przedmiotów za każdym razem, gdy chcesz tylko kawałek. – user2357112

+0

Tak, wiem o tym, ale problem polega na tym, że nie mogę znaleźć innej metody dzielenia słownika na porcje o równych rozmiarach. – badc0re

+1

Spróbuj przepisu '' grouper' z 'itertools'] (https://docs.python.org/2.7/library/itertools.html#recipes). – jonrsharpe

Odpowiedz

25

Ponieważ Słownik jest tak duża, że ​​byłoby lepiej, aby zachować wszystkie elementy związane być tylko iteratory i generatory, podobnie jak to

from itertools import islice 

def chunks(data, SIZE=10000): 
    it = iter(data) 
    for i in xrange(0, len(data), SIZE): 
     yield {k:data[k] for k in islice(it, SIZE)} 

biegu próbnego:

for item in chunks({i:i for i in xrange(10)}, 3): 
    print item 

Wyjście

{0: 0, 1: 1, 2: 2} 
{3: 3, 4: 4, 5: 5} 
{8: 8, 6: 6, 7: 7} 
{9: 9} 
1

Inną metodą jest iteratory skompresowanie:

>>> from itertools import izip_longest, ifilter 
>>> d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7, 'h':8} 

Tworzenie listy z kopiami iteratorów DICT (liczba kopii jest liczba elementów w dicts wynikowych). Przekazując każdy iterator z listy chunks do izip_longest otrzymasz potrzebną liczbę elementów z źródła dict (ifilter, które zostały użyte do usunięcia None z wyników zip). Z wyrażeniem generatora można zmniejszyć zużycie pamięci:

>>> chunks = [d.iteritems()]*3 
>>> g = (dict(ifilter(None, v)) for v in izip_longest(*chunks)) 
>>> list(g) 
[{'a': 1, 'c': 3, 'b': 2}, 
{'e': 5, 'd': 4, 'g': 7}, 
{'h': 8, 'f': 6}] 
Powiązane problemy