1

長さが等しくない可能性のある 2 つのリストをインターリーブできるようにしたいと考えています。私が持っているものは次のとおりです。

  def interleave(xs,ys):
    a=xs
    b=ys
    c=a+b
    c[::2]=a
    c[1::2]=b
    return c

これは、長さが等しいか、ちょうど +/-1 のリストでうまく機能します。しかし、xs=[1,2,3] と ys= ["hi,"bye","no","yes","why"] とすると、次のメッセージが表示されます。

c[::2]=a
ValueError: attempt to assign sequence of size 3 to extended slice of size 4

インデックス作成を使用してこれを修正するにはどうすればよいですか? または for ループを使用する必要がありますか? 編集:私が欲しいのは、余分な値を最後に表示することです。

4

4 に答える 4

7

ここで使用できitertools.izip_longestます:

>>> from itertools import izip_longest
>>> xs = [1,2,3]
>>> ys = ["hi","bye","no","yes","why"]
>>> s = object()
>>> [y for x in izip_longest(xs, ys, fillvalue=s) for y in x if y is not s]
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

itertoolsroundrobinのレシピを使用すると、ここではセンチネル値は必要ありません。

from itertools import *
def roundrobin(*iterables):
    "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))

デモ:

>>> list(roundrobin(xs, ys))
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']
>>> list(roundrobin(ys, xs))
['hi', 1, 'bye', 2, 'no', 3, 'yes', 'why']
于 2013-11-09T22:32:18.280 に答える
7

使用できますheapq.merge

xs = [1, 2, 3]
ys = ['hi', 'bye', 'no', 'yes', 'why']

import heapq
interleaved = [v for i, v in heapq.merge(*[enumerate(el) for el in (xs, ys)])]
# [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

これにより、センチネル値とフラット化の必要がなくなります。

アイテムを比較することなく、より効果的にこれを達成するには、代わりにラウンドロビン レシピを使用します。

于 2013-11-09T22:33:35.397 に答える
2

さて、ここに私のエントリがあります:

>>> from itertools import chain
>>> xs = [1,2,3]
>>> ys = ["hi","bye","no","yes","why"]
>>> xi, yi = iter(xs), iter(ys)
>>> list(chain.from_iterable(zip(xi, yi))) + list(xi) + list(yi)
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

あるいは、

>>> [i for row in zip(xi, yi) for i in row] + list(xi) + list(yi)

も機能していたでしょう(@hcwhsaが使用しているように、これは平坦化のためのlistcompイディオムです)。私の最初の考えは

>>> list(zip(*sorted(list(enumerate(xs)) + list(enumerate(ys)))))[1]
(1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why')

しかし、それは @Jon Clements のはるかに効率の悪いバージョンです (私は非効率的なソートを使用し、彼は効率的なヒープ キューを使用しました)。

[私はcycle動作するものを取得しようと実験してきましたが、思ったほど簡単ではないようです: そして、@hcwsha が投稿したラウンドロビンレシピの再実装に向けて単純に取り組んでいたことがわかりました。それを終わらせる意味はありません。:^) ]

于 2013-11-09T23:06:14.937 に答える
0

シンプルに保ちます:

def interleave(xs,ys):
    stop = min(len(xs), len(ys))
    suffix = max(xs, ys, key = len)[stop:]
    out = list()
    for pair in zip(xs, ys):
        out.extend(pair)
    out.extend(suffix)
    return out

警告:
Python 2.7
は、リストが引数として渡されることを前提としています。

于 2013-11-09T23:20:26.357 に答える