Подтвердить что ты не робот

Разделить словарь пополам?

Каков наилучший способ разделить словарь пополам?

d = {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 4, 'key5': 5}

Я хочу сделать это:

d1 = {'key1': 1, 'key2': 2, 'key3': 3}
d2 = {'key4': 4, 'key5': 5}

Не важно, какие ключи/значения входят в каждый словарь. Я просто ищу простейший способ разделить словарь на два.

4b9b3361

Ответ 1

Это сработает, хотя я не тестировал краевые случаи:

>>> d = {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 4, 'key5': 5}
>>> d1 = dict(d.items()[len(d)/2:])
>>> d2 = dict(d.items()[:len(d)/2])
>>> print d1
{'key1': 1, 'key5': 5, 'key4': 4}
>>> print d2
{'key3': 3, 'key2': 2}

Ответ 2

Вот как это сделать, используя итератор над элементами в словаре и itertools.islice:

import itertools

def splitDict(d):
    n = len(d) // 2          # length of smaller half
    i = iter(d.items())      # alternatively, i = d.iteritems() works in Python 2

    d1 = dict(itertools.islice(i, n))   # grab first n items
    d2 = dict(i)                        # grab the rest

    return d1, d2

Ответ 3

d1 = {key: value for i, (key, value) in enumerate(d.viewitems()) if i % 2 == 0}
d2 = {key: value for i, (key, value) in enumerate(d.viewitems()) if i % 2 == 1}

Ответ 4

Если вы используете python +3.3 и хотите, чтобы ваши расщепленные словари были одинаковыми для разных вызовов python, не используйте .items, так как значения хэша ключей, определяющие порядок .items(), будут меняться между вызовами python. См. Хэш-рандомизация


Ответ 5

Ответ jone не работал у меня. Мне нужно было указать в список, прежде чем я смог проиндексировать результат вызова .items(). (Я запускаю Python 3.6 в примере)

d = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5}
split_idx = 3
d1 = dict(list(d.items())[:split_idx])
d2 = dict(list(d.items())[split_idx:])

"""
output:
d1
{'one': 1, 'three': 3, 'two': 2}
d2
{'five': 5, 'four': 4}
"""

Обратите внимание, что dicts не обязательно сохраняются в порядке создания, поэтому индексы могут быть перемешаны.

Ответ 6

Вот функция, которая может использоваться для разделения словаря на любые разделы.

import math

def linch_dict_divider(raw_dict, num):
    list_result = []
    len_raw_dict = len(raw_dict)
    if len_raw_dict > num:
        base_num = len_raw_dict / num
        addr_num = len_raw_dict % num
        for i in range(num):
            this_dict = dict()
            keys = list()
            if addr_num > 0:
                keys = raw_dict.keys()[:base_num + 1]
                addr_num -= 1
            else:
                keys = raw_dict.keys()[:base_num]
            for key in keys:
                this_dict[key] = raw_dict[key]
                del raw_dict[key]
            list_result.append(this_dict)

    else:
        for d in raw_dict:
            this_dict = dict()
            this_dict[d] = raw_dict[d]
            list_result.append(this_dict)

    return list_result

myDict = {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 4, 'key5': 5}
print myDict
myList = linch_dict_divider(myDict, 2)
print myList

Ответ 7

Мы можем сделать это эффективно с помощью itertools.zip_longest() (обратите внимание, что это itertools.izip_longest() в 2.x):

from itertools import zip_longest
d = {'key1': 1, 'key2': 2, 'key3': 3, 'key4': 4, 'key5': 5}
items1, items2 = zip(*zip_longest(*[iter(d.items())]*2))
d1 = dict(item for item in items1 if item is not None)
d2 = dict(item for item in items2 if item is not None)

Что дает нам:

>>> d1
{'key3': 3, 'key1': 1, 'key4': 4}
>>> d2
{'key2': 2, 'key5': 5}

Ответ 8

Если вы использовали NumPy, то вы можете сделать это:

def divide_dict(dictionary, chunk_size):

'''
Divide one dictionary into several dictionaries

Return a list, each item is a dictionary
'''

import numpy, collections

count_ar = numpy.linspace(0, len(dictionary), chunk_size+1, dtype= int)
group_lst = []
temp_dict = collections.defaultdict(lambda : None)
i = 1
for key, value in dictionary.items():
    temp_dict[key] = value
    if i in count_ar:
        group_lst.append(temp_dict)
        temp_dict = collections.defaultdict(lambda : None)
    i += 1
return group_lst