2016-10-31 8 views
3

複数のフィールドの文字列のリストからリストのリストを作成し、それを理解できるかどうか疑問に思っています。複数の変数?

入力:

inputs = ["1, foo, bar", "2, tom, jerry"] 

所望の出力:

[[1, "foo", "bar"], [2, "tom", "jerry"]] 

理解に文字列を分割が簡単です:

>>> [s.split(",") for s in inputs] 
[['1', ' foo', ' bar'], ['2', ' tom', ' jerry']] 

しかし、私がアクセスする方法、トラブルを考え出すを抱えています文字列の後の列は、内部に分割されています。なぜなら、variaが必要と思われるからです譲渡割当。以下は、有効なPythonではありませんが、私が探しているものを示しています

[[int(x), y.strip(), z.strip() for x,y,z = s.split(",")] for s in inputs] 
    or 
[[int(v[0]), v[1].strip(), v[2].strip() for v = s.split(",")] for s in inputs] 

出力は変数の関数で構成することができるように理解内部変数を割り当てることがある方法ですか?ループは簡単ですが、入力を変換してリストを生成することは、「理解力」のようです。

outputs = [] 
for s in inputs: 
    x,y,z = s.split(",") 
    outputs.append([int(x), y.strip(), z.strip()]) 
+0

あなたはそれらのインデックスを持つ要素にアクセスすることができます。 lst [0] [0] 'は '1'、' lst 'は '' ' [0] [1] 'は' foo'などとなります。変数が必要な場合は、おそらくキー付きのマップとして格納する必要があります。 – shaktimaan

+4

'[...入力のs(s.split( '、')のx、y、zの)]' – jonrsharpe

答えて

3

あなたのリスト内包で2 for節でこれを行うことができます。最初はリスト内の項目を反復処理します。 2番目は、文字列を分割して得られたリストを含む単一項目リストを繰り返します(3つの別々の変数に展開するために必要です)。

[[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]] 

for節はやや直感に反するために行くが、それはあなたがネストされたforループとしてそれを書くだろう方法と一致します。

ネストされた理解(実際にはジェネレータ表現)のJon Sharpeの使用は似ており、おそらくより明確です。複数のfor句の使用は、私にとっては常に混乱しているようです。主に私はここでそれを利用できるかどうかを見たいと思っていました。

1

あなたが本当に1行でそれをしたい場合は、それが明確なコードではありませんが、あなたは、このような何かを行うことができます(最初の行は二行目が出力され、コードです)。

>>> [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs] 
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 

またはこれです。

>>> [(lambda x: [int(x[0]), x[1].strip(), x[2].strip()])(s.split(",")) for s in inputs] 
[[1, 'foo', 'bar'], [2, 'tom', 'jerry'] 

編集: 最高の回答IMHOのためのjonrsharpeさんのコメントを参照してください。

+0

私はラムダを考えていましたが、可能ならば避けることを望んでいました。 – Dave

1

あなたはラムダ関数とリスト内包

def clean(x): 
    return [int(x[0]), x[1].strip(), x[2].strip()] 

map(clean,[s.split(",") for s in inputs]) 
# Output: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 

でマップを使用することができます。

map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs]) 
0

もう1つの可能な解決策

>>> inputs = [[1, "foo", "bar"], [2, "tom", "jerry"]] 
>>> list_of_dicts = [{"var{}".format(k): v for k, v in enumerate(s, start=1)} for s in inputs] 
>>> list_of_dicts[0]['var1'] 
1 
>>> list_of_dicts[0]['var2'] 
'foo' 
1

すべての提案をありがとう - それは可能な種々の技術を見るのは素晴らしいことだ、だけでなく、Pythonのの禅への反例「があるべきである - そして好ましくは一つだけ - それを行う明らかな方法。"

4つのソリューションはすべて同じように美しいので、欲しい緑色のチェックを1つだけにするのはちょっと不公平です。#1が最もクリーンでベストなアプローチであることに同意します。簡単に理解することができますが、理解の中でラムダを使用する必要はありません。#3はマップ付きのイテレータを作成するのにはいいですが、それを反復する余分な手順が必要な小さなデメリットがあります。それはネストされたものです - 私は彼らが "内側、外側"の代わりに "第1、第2"の順序で行くことを覚えていれば、#1は答えの形式ではないので、#4は最も驚くべき点数を得ます。

ありがとうございます。

inputs = ["1, foo, bar", "2,tom, jerry"] 

outputs1 = [[int(x), y.strip(), z.strip()] for x,y,z in (s.split(',') for s in inputs)] 
print("1:", outputs1)  # jonrsharpe 

outputs2 = [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs] 
print("2:", outputs2)  # yper 

outputs3 = [z for z in map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs])] 
print("3:", outputs3)  # user2314737 

outputs4 = [[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]] 
print("4:", outputs4)  # kindall 

結果:

1: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
2: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
3: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
4: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]