gpt4 book ai didi

python - 如何根据某些条件对单个可迭代对象进行 "round-robin"?

转载 作者:太空狗 更新时间:2023-10-30 01:26:44 25 4
gpt4 key购买 nike

我有一个字典列表,我想对其进行循环排序。

sample = [
{'source': 'G', '"serial"': '0'},
{'source': 'G', '"serial"': '1'},
{'source': 'G', '"serial"': '2'},
{'source': 'P', '"serial"': '30'},
{'source': 'P', '"serial"': '0'},
{'source': 'P', '"serial"': '1'},
{'source': 'P', '"serial"': '2'},
{'source': 'P', '"serial"': '3'},
{'source': 'T', '"serial"': '2'},
{'source': 'T', '"serial"': '3'}
]

我想要这样的结果:

sample_solved = [
{'source': 'G', '"serial"': '0'},
{'source': 'P', '"serial"': '30'},
{'source': 'T', '"serial"': '2'},
{'source': 'G', '"serial"': '1'},
{'source': 'P', '"serial"': '1'},
{'source': 'T', '"serial"': '3'},
{'source': 'G', '"serial"': '2'},
{'source': 'P', '"serial"': '0'},
{'source': 'P', '"serial"': '2'},
{'source': 'P', '"serial"': '3'}
]

我的解决方法如下:

def roundrobin(*iterables):
# took from here https://docs.python.org/3/library/itertools.html#itertools-recipes

"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis

pending = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))

def solve():
items_by_sources = collections.defaultdict(list)

for item in sample2:
items_by_sources[item["source"]].append(item)

t, p, g = items_by_sources.values()

print(list(roundrobin(t, p, g)))

使用 Python 的 defaultdict 按来源分隔项目,然后使用我从 Python 的文档中获得的循环解决方案。

但是,该解决方案并未涵盖所有情况,例如 t, p, g = items_by_sources.values() 将在缺少一个源或添加新源时中断。

我怎样才能制定一个解决方案来涵盖更多的边缘情况并使解决方案成为 pythonic?

最佳答案

这是一个使用 itertools.groupby() 的解决方案将您的输入分成适当的组:

from itertools import groupby

def grouprobin(iterable, key):
groups = [list(g) for k, g in groupby(iterable, key)]
while groups:
group = groups.pop(0)
yield group.pop(0)
if group:
groups.append(group)

由于 groupby() 的工作方式,在您从文档中获取的 roundrobin() 版本中迭代器的巧妙使用并不是很有帮助,所以我以一种希望更容易理解的方式重写了它:

  1. 对可迭代对象进行分组
  2. 当您还有剩余的组时:

    1. 从组列表的前面弹出第一个组

    2. 弹出该组中的第一个项目,并产生它。

    3. 如果组中还有项目,将其追加到列表末尾。

这是实际操作:

>>> sample_solved = list(grouprobin(sample, key=lambda d: d['source']))
>>> from pprint import pprint
>>> pprint(sample_solved)
[{'"serial"': '0', 'source': 'G'},
{'"serial"': '30', 'source': 'P'},
{'"serial"': '2', 'source': 'T'},
{'"serial"': '1', 'source': 'G'},
{'"serial"': '0', 'source': 'P'},
{'"serial"': '3', 'source': 'T'},
{'"serial"': '2', 'source': 'G'},
{'"serial"': '1', 'source': 'P'},
{'"serial"': '2', 'source': 'P'},
{'"serial"': '3', 'source': 'P'}]

上面的 grouprobin() 版本假定您的列表已经排序。如果不是,则需要在分组之前对其进行排序:

def grouprobin(iterable, key):
groups = [list(g) for k, g in groupby(sorted(iterable, key=key), key)]
while groups:
group = groups.pop(0)
yield group.pop(0)
if group:
groups.append(group)

关于python - 如何根据某些条件对单个可迭代对象进行 "round-robin"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42560404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com