5

2 つのリストを引数として取り、それらをインターリーブする Python 関数を作成しようとしています。コンポーネント リストの順序は維持する必要があります。リストの長さが同じでない場合、長いリストの要素は結果のリストの最後に配置されます。たとえば、これをシェルに入れたいと思います:

interleave(["a", "b"], [1, 2, 3, 4])

そしてこれを取り戻します:

["a", 1, "b", 2, 3, 4]

あなたが私を助けることができれば、私はそれを感謝します.

4

4 に答える 4

1

これを試すことができます:

In [30]: from itertools import izip_longest

In [31]: l = ['a', 'b']

In [32]: l2 = [1, 2, 3, 4]

In [33]: [item for slist in izip_longest(l, l2) for item in slist if item is not None]
Out[33]: ['a', 1, 'b', 2, 3, 4]

izip_longest2 つのリストを一緒に「圧縮」しますが、最短のリストの長さで停止するのではなく、最長のリストが使い果たされるまで続けます。

In [36]: list(izip_longest(l, l2))
Out[36]: [('a', 1), ('b', 2), (None, 3), (None, 4)]

次に、圧縮されたリスト内の各ペアの各アイテムを反復処理してアイテムを追加し、値が のアイテムを省略しますNone。@Blckknight で指摘されているように、元のリストにNone既に値がある場合、これは正しく機能しません。あなたの状況でそれが可能な場合は、のfillvalueプロパティを使用して、izip_longest以外のもので埋めることができますNone(@Blckknightが彼の答えで行っているように)。

上記の例を関数として次に示します。

In [37]: def interleave(*iterables):
   ....:     return [item for slist in izip_longest(*iterables) for item in slist if item is not None]
   ....:

In [38]: interleave(l, l2)
Out[38]: ['a', 1, 'b', 2, 3, 4]

In [39]: interleave(l, l2, [44, 56, 77])
Out[39]: ['a', 1, 44, 'b', 2, 56, 3, 77, 4]
于 2012-11-05T03:00:09.810 に答える
1

モジュールのさまざまなビットを使用して、これを行う方法を次に示しitertoolsます。2 つだけでなく、任意の数の iterable に対して機能します。

from itertools import chain, izip_longest # or zip_longest in Python 3
def interleave(*iterables):

    sentinel = object()
    z = izip_longest(*iterables, fillvalue = sentinel)
    c = chain.from_iterable(z)
    f = filter(lambda x: x is not sentinel, c)

    return list(f)
于 2012-11-05T02:55:15.517 に答える
0

別の解決策は以下に基づいています:私はそれを手でどのように行うでしょうか?さて、ほとんど手作業で、組み込みを使用しzip()、短いリストの長さを長いリストの末尾で圧縮した結果を拡張します。

#!python2

def interleave(lst1, lst2):
    minlen = min(len(lst1), len(lst2))        # find the length of the shorter
    tail = lst1[minlen:] + lst2[minlen:]      # get the tail
    result = []
    for t in zip(lst1, lst2):                 # use a standard zip
        result.extend(t)                      # expand tuple to two items
    return result + tail                      # result of zip() plus the tail

print interleave(["a", "b"], [1, 2, 3, 4])
print interleave([1, 2, 3, 4], ["a", "b"])
print interleave(["a", None, "b"], [1, 2, 3, None, 4])

結果を出力します。

['a', 1, 'b', 2, 3, 4]
[1, 'a', 2, 'b', 3, 4]
['a', 1, None, 2, 'b', 3, None, 4]
于 2012-11-05T07:53:15.267 に答える
0

あまりエレガントな解決策ではありませんが、それでも役立つかもしれません

def interleave(lista, listb):
    (tempa, tempb) = ([i for i in reversed(lista)], [i for i in reversed(listb)])
    result = []
    while tempa or tempb:
        if tempa:
            result.append(tempa.pop())
        if tempb:
            result.append(tempb.pop())

    return result

または1行で

   def interleave2(lista, listb):
    return reduce(lambda x,y : x + y,
                  map(lambda x: x[0] + x[1],
                      [(lista[i:i+1], listb[i:i+1])
                       for i in xrange(max(len(lista),len(listb)))]))
于 2012-11-05T06:39:59.327 に答える