如何快速将字典拆分为多个字典
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 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你