Я нашел решение, но он очень медленный:
def chunks(self,data, SIZE=10000):
for i in xrange(0, len(data), SIZE):
yield dict(data.items()[i:i+SIZE])
Есть ли у вас идеи без использования внешних модулей (numpy и т.д.).
Я нашел решение, но он очень медленный:
def chunks(self,data, SIZE=10000):
for i in xrange(0, len(data), SIZE):
yield dict(data.items()[i:i+SIZE])
Есть ли у вас идеи без использования внешних модулей (numpy и т.д.).
Поскольку словарь настолько велик, было бы лучше, чтобы все элементы были просто итераторами и генераторами, такими как
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)}
Пример прогона:
for item in chunks({i:i for i in xrange(10)}, 3):
print item
Выход
{0: 0, 1: 1, 2: 2}
{3: 3, 4: 4, 5: 5}
{8: 8, 6: 6, 7: 7}
{9: 9}
Другой метод - итераторы zipping:
>>> from itertools import izip_longest, ifilter
>>> d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7, 'h':8}
Создайте список с копиями диктовых итераторов (количество копий - это количество элементов в результатах dicts). Передавая каждый итератор из chunks
списка izip_longest
, вы получите необходимое количество элементов из источника dict (ifilter
используется для удаления None
из результатов zip). С выражением генератора вы можете уменьшить использование памяти:
>>> 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}]
Решение Python3, основанное на подходе @ndpu:
from itertools import zip_longest
chunks = [self.data_to_process.items()] * self.no_of_processes
g = (dict(filter(None, v)) for v in zip_longest(*chunks))
chunked_data = list(g)
Узлы:
Этот код берет большой словарь и разбивает его на список небольших словарей. Переменная max_limit указывает максимальное количество пар ключ-значение, разрешенных в под-словаре. Этот код не требует особых усилий, чтобы разбить словарь, только один полный анализ словарного объекта.
import copy
def split_dict_to_multiple(input_dict, max_limit=200):
"""Splits dict into multiple dicts with given maximum size.
Returns a list of dictionaries."""
chunks = []
curr_dict ={}
for k, v in input_dict.items():
if len(curr_dict.keys()) < max_limit:
curr_dict.update({k: v})
else:
chunks.append(copy.deepcopy(curr_dict))
curr_dict = {k: v}
# update last curr_dict
chunks.append(curr_dict)
return chunks
import numpy as np
chunk_size = 3
chunked_data = [[k, v] for k, v in d.items()]
chunked_data = np.array_split(chunked_data, chunk_size)
После этого у вас есть ndarray
который можно повторять так:
for chunk in chunked_data:
for key, value in chunk:
print(key)
print(value)
Который может быть переназначен списку диктов с помощью простого цикла for.