22

リスト内包表記の各反復の値を1回だけ分割する方法があるかどうかを調べようとしていますが、出力では2回使用します。

私が解決しようとしている問題の例として、次の文字列があります。

a = "1;2;4\n3;4;5"

そして、私はこれを実行したいと思います:

>>> [(x.split(";")[1],x.split(";")[2]) for x in a.split("\n") if x.split(",")[1] != 5]
[('2', '4'), ('4', '5')]

スプリットを3回実行する必要はありません。したがって、次のようなものです(これは明らかに無効な構文ですが、メッセージを伝えるのに十分であることが望まれます)。

[(x[1],x[2]) for x.split(";") in a.split("\n") if x[1] != 5]

この質問では、文字列の2番目と3番目の列を取得するための凝った方法を探していません。これは、具体的な例を提供する方法にすぎません。もちろん、使用例については次のようにできます。

[x.split(";")[1:3] for x in a.split("\n")]

私が考えた可能な解決策:

  1. リスト内包表記を使用しない
  2. そのままにしておきます
  3. を使用しcsv.DictReader、列に名前を付けStringIOて、入力を与えるようなものを使用します。

これは主に、特定のケースではなく、使用できる優れたパターンであるため、「なぜこれを実行したいのか」または「これは何のためにあるのか」という種類の質問に答えるのは困難です。

更新:以下の解決策を読んだ後、私はいくつかの速度テストを実行しました。そして、非常に基本的なテストで、提供されたソリューションが上記の単純なソリューションよりも35%高速であることがわかりました。

4

2 に答える 2

33

ジェネレータ式にラップされたリスト内包表記を使用できます。

[(x[1],x[2]) for x in (x.split(";") for x in a.split("\n")) if x[1] != 5]
于 2012-04-25T03:31:47.163 に答える
7

を開始し、代入式(PEP 572)(演算子)Python 3.8を導入すると、同じ式を2回呼び出さないようにするために、リスト内包内でローカル変数を使用できます。:=

この例では、式の結果を使用して、が;に等しくない場合にリストをフィルタリングしながら、の評価にline.split(';')変数として名前を付けることができます。したがって、再利用してマップされた値を生成します。partsparts[1]5parts

# text = '1;2;4\n3;4;5'
[(parts[1], parts[2]) for line in text.split('\n') if (parts := line.split(';'))[1] != 5]
# [('2', '4'), ('4', '5')]
于 2019-04-27T15:41:27.757 に答える