あなたが何を望んでいるかを理解していると仮定するとitertools.zip_longest
、itertools.groupby
とを組み合わせることで比較的簡単に実行できitertools.chain.from_iterable()
ます。
最初に項目をセット ( "a"
s、"b"
s など...) にグループ化し、必要な順序 (各セットから 1 つ) になるように圧縮し、chain を使用して 1 つのリストを作成し、次に削除します。圧縮によって導入された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
、センチネル オブジェクトを作成し、それに対して ID をチェックします。
zip の代わりに、ドキュメントに記載されているレシピを使用する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()
ジェネレーターからリストを作成していることに気付くかもしれませんが、これは無駄に思えるかもしれません.理由はdocsから来ています:
返されるグループ自体は、基になる iterable を groupby() と共有するイテレータです。ソースが共有されているため、groupby() オブジェクトが進められると、前のグループは表示されなくなります。そのため、後でそのデータが必要になった場合は、リストとして保存する必要があります。