如何快速将字典拆分为多个字典

Posted

技术标签:

【中文标题】如何快速将字典拆分为多个字典【英文标题】:How to split dictionary into multiple dictionaries fast 【发布时间】:2014-05-17 16:59:57 【问题描述】:

我找到了解决方案,但速度真的很慢:

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

你有什么不使用外部模块(numpy等)的想法

【问题讨论】:

不要一直打电话给items。每次您只想要一个切片时,您都会创建一个所有项目的新列表。 是的,我知道,但问题是我找不到其他方法将我的字典分成大小相等的块。 试试grouper recipe from itertools @badc0re:不过,不要一直打电话给items。做一次。 注意:我看不出拆分字典有什么用......你到底在做什么? 【参考方案1】:

既然字典这么大,最好让所有涉及的项目都只是迭代器和生成器,像这样

from itertools import islice

def chunks(data, SIZE=10000):
    it = iter(data)
    for i in range(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

【讨论】:

很好的答案。在 Python3 中使用 range() 而不是 xrange() 您能否详细说明迭代器/生成器如何/为什么更可取 - 是为了提高内存效率吗?【参考方案2】:

另一种方法是迭代器压缩:

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

用字典迭代器的副本创建一个列表(副本数是结果字典中的元素数)。通过将每个迭代器从chunks 列表传递到izip_longest,您将从源字典中获得所需数量的元素(ifilter 用于从压缩结果中删除None)。使用生成器表达式可以降低内存使用量:

>>> 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]

【讨论】:

【参考方案3】:
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 循环将其重新分配给 dicts 列表。

【讨论】:

可能被否决了,因为使用 numpy ndarray 来分块本地字典显然是一种过度杀伤力。 OP 表示需要不使用任何外部模块,明确提到 numpy。【参考方案4】:

此代码采用一个大字典并将其拆分为一个小字典列表。 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

【讨论】:

最好用代码 sn-ps 提供一些解释【参考方案5】:

对于 Python 3+。

xrange() 在 Python 3+ 中重命名为 range()

你可以使用;

from itertools import islice

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

示例:

for item in chunks(i:i for i in range(10), 3):
   print(item)

有以下输出。

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

【讨论】:

【参考方案6】:

此代码适用于 Python 3.8,不使用任何外部模块:

def split_dict(d, n):
    keys = list(d.keys())
    for i in range(0, len(keys), n):
        yield k: d[k] for k in keys[i: i + n]


for item in split_dict(i: i for i in range(10), 3):
    print(item)

打印这个:

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

...甚至可能比 thefourtheye 的(当前)accepted answer 稍快:

from hwcounter import count, count_end


start = count()
for item in chunks(i: i for i in range(100000), 3):
    pass
elapsed = count_end() - start
print(f'elapsed cycles: elapsed')

start = count()
for item in split_dict(i: i for i in range(100000), 3):
    pass
elapsed = count_end() - start
print(f'elapsed cycles: elapsed')

打印

elapsed cycles: 145773597
elapsed cycles: 138041191

【讨论】:

为什么不使用 Python 的 'timeit' 模块来衡量性能?

以上是关于如何快速将字典拆分为多个字典的主要内容,如果未能解决你的问题,请参考以下文章

将字典列表拆分为多个字典列表

2021-10-15:单词拆分。给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你

python 如何快速找到多个字典中出现的公共键

如何将字符串字典转换为字典并拆分为单独的列

如何将多个值添加到python中的字典键? [关闭]

如何快速找到多个字典中的公共键(1.4)