假设我理解你想要什么,它可以通过结合itertools.zip_longest
,itertools.groupby
和相对容易地完成itertools.chain.from_iterable()
:
我们首先将项目分组("a"
s、"b"
s 等),我们将它们压缩以按照您想要的顺序获取它们(每组一个),使用链生成单个列表,然后删除None
压缩引入的值。
>>> [item for item in itertools.chain.from_iterable(itertools.zip_longest(*[list(x) for _, x in itertools.groupby(to_be)])) if item]
['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'd', 'd']
但是,您可能希望分离出一些列表推导以使其更具可读性:
>>> groups = itertools.zip_longest(*[list(x) for _, x in itertools.groupby(to_be)])
>>> [item for item in itertools.chain.from_iterable(groups) if item]
['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'd', 'd']
(给定的版本是 3.x,对于 2.x,你会想要izip_longest()
。)
与往常一样,如果您期望空字符串、0 等......那么您将想要这样做if item is not None
,并且如果您需要保持None
值的完整,请创建一个哨兵对象并检查其身份。
您还可以使用文档中给出的roundrobin()
配方,作为压缩的替代方法,这使得它变得如此简单:
>>> list(roundrobin(*[list(x) for _, x in itertools.groupby(to_be)]))
['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'd', 'd']
最后一点,观察者可能会注意到我从groupby()
生成器中制作列表,这可能看起来很浪费,原因来自文档:
返回的组本身就是一个迭代器,它与 groupby() 共享底层迭代。因为源是共享的,所以当 groupby() 对象前进时,之前的组不再可见。因此,如果以后需要该数据,则应将其存储为列表。