web-dev-qa-db-ja.com

条件が真の場合、隣接するリスト要素を持つタプルのリストを作成します

タプルの内容が番号9であり、リスト内でその前の番号であるタプルのリストを作成しようとしています。

入力リスト:

myList = [1, 8, 9, 2, 4, 9, 6, 7, 9, 8]

目的の出力:

sets = [(8, 9), (4, 9), (7, 9)]

コード:

sets = [list(Zip(myList[i:i], myList[-1:])) for i in myList if i==9]

現在の結果:

[[], [], []]
30
user6201619

よりクリーンなPythonicアプローチ:

_>>> [(x,y) for x,y in Zip(myList, myList[1:]) if y == 9]
[(8, 9), (4, 9), (7, 9)]
_

上記のコードは何をしていますか:

  • Zip(some_list, some_list[1:])は、隣接する要素のペアのリストを生成します。
  • そのタプルを使用して、2番目の要素が_9_に等しいという条件でフィルタリングします。完了です:)
39
UltraInstinct

問題の一部は、myList[i:i]が常に空のリストを返すことです。スライスの終わりは排他的であるため、a_list[0:0]を実行すると、存在するa_listの要素を取得しようとしますbetween index0とindex0。

あなたは正しい方向に進んでいますが、リストをそれ自体で圧縮したいと考えています。

[(x, y) for x, y in Zip(myList, myList[1:]) if y==9]
17
Morgan Thrapp

あなたはかなり近かったので、始めたばかりの場合はもっと直感的な別の方法を紹介します。

_sets = [(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]
_

リストの長さの範囲内のインデックスを取得し、位置iの値が_9_と等しい場合は、隣接する要素を取得します。

結果は次のとおりです。

_sets
[(8, 9), (4, 9), (7, 9)]
_

これは他のアプローチよりも効率が悪いですが、別の方法を示すために削除を取り消すことにしました。代わりにenumerate()を使用すると、少し速く進むことができます。

_sets = [(myList[i-1], j) for i, j in enumerate(myList) if j == 9]
_

注意その_myList[0] = 9_Zipなしの理解の振る舞いとZipの理解度はdifferentです。

具体的には、_myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8]_の場合:

_[(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]
# results in: [(8, 9), (8, 9), (4, 9), (7, 9)]
_

一方:

_[(x, y) for x, y in Zip(myList, myList[1:]) if y==9]
# results in: [(8, 9), (4, 9), (7, 9)]
_

これらのどれがあなたの基準に合うかを決めるのはあなた次第です、私はそれらがすべての場合に同じように振る舞うわけではないことを指摘しているだけです。

誰も機能的なアプローチを追加していないのは本当に驚くべきことです。

別の代替回答は filter を使用することです。この組み込み関数は、特定の関数に対してTrueを返すリストに存在するすべての要素で構成されるイテレーター(Python2のリスト)を返します。

>>> myList = [1,8,9,2,4,9,6,7,9,8]
>>> list(filter(lambda x:x[1]==9,Zip(myList, myList[1:])))
[(8, 9), (4, 9), (7, 9)]

list呼び出しはpython3 + でのみ必要であることに注意してください。機能的アプローチとリスト内包表記の違いについては、 この投稿の詳細 で説明しています。

5
Bhargav Rao

イテレータを作成することで、スライスせずにそれを行うこともできます。

l = myList = [1,8,9,2,4,9,6,7,9,8]

it1, it2 = iter(l), iter(l)
# consume first element from it2 -> leaving 8,9,2,4,9,6,7,9,8
next(it2, "")
# then pair up, (1,8), (8,9) ...
print([(i, j) for i,j in Zip(it1, it2) if j == 9])

または、 ペアワイズレシピ を使用してペアを作成します

from itertools import tee, izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Python3を使用している場合は、teeをインポートし、通常のZipを使用します。

5

私のソリューションは、ゼロインデックスチェックを備えたジムの高度なソリューションの1つに似ています

myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8]

[(myList[i-1], x) for i, x in enumerate(myList) if x==9 and i!=0]

# [(8, 9), (4, 9), (7, 9)]
1
Jiacai Liu