2009-04-21 14 views
8

次のようなことが可能ですか?Pythonのリスト内包の複数のステートメント

list1 = ... 

currentValue = 0 
list2 = [currentValue += i, i for i in list1] 

私はそれを試しましたが動作しませんでしたか?それらを書くための正しい構文は何ですか?

EDIT:printステートメントが例でした。実際には、ループ外の値をインクリメントしています。

+0

をするために、文の通常の何が問題なのですか?あなたは完全に良い声明を持っているとき、なぜこれを気にかけますか?あなたは何を達成しようとしていますか? –

+1

Pythonのリストcompherensionsで可能かどうかは分かりません。 –

答えて

23

できません。 Pythonの式の中に入ります。それは故意に言語から設計された合併症でした。この問題を解決するには、となっているという複雑なことを使用してください:generators。ウォッチ:

def total_and_item(sequence): 
    total = 0 
    for i in sequence: 
     total += i 
     yield (total, i) 

list2 = list(total_and_item(list1)) 

ジェネレータは、あなたのような例がそうしようと、それは見た目だけのよう、これまで見た項目の実行中の集計を保持し、各項目にそれを接頭辞。もちろん、単純なループであっても、単純なものでも、上に空のリストを作成し、append()をたくさん呼び出すこともできます。 :-)編集済み例えば

+0

+1は、式が式から除外されていることに言及しています(複数のステートメント:-)ではなく、より明示的なアプローチの推奨を加えています。 –

0

まず第一に、あなたはおそらくprintを使用する必要はありません。何も返さないので、ただのものを印刷したい場合は、通常のforループを使用してください。あなたが探していることは次のとおりです。

>>> list1 = (1,2,3,4) 
>>> list2 = [(i, i*2) for i in list1] # Notice the braces around both items 
>>> print(list2) 
[(1, 2), (2, 4), (3, 6), (4, 8)] 
2

私はあなたが何をしようとしてはかなりわからないんだけど、それはおそらく

list2 = [(i, i*2, i) for i in list1] 
print list2 
リスト内包でのステートメントは単一である必要があり

のようなものです声明が、あなたは常にそれの関数呼び出し作ることができます:

def foo(i): 
    print i 
    print i * 2 
    return i 
list2 = [foo(i) for i in list1] 
2

をここでanother questionからの例です:

[i for i,x in enumerate(testlist) if x == 1] 

列挙発生器はI、Xに入る2つのタプルを返します。

1

印刷は、リスト内包で呼ばれる奇妙なことです。うまくいかないコードだけでなく、あなたが望む出力を見せてくれれば助けになるでしょう。

はここにあなたのための2つの推定されています。いずれにしても、重要な点は、リストの理解の中のvalueステートメントがの単一のの値でなければならないことです。一度に複数の項目を挿入することはできません。 (それはあなたが何をしようとしてなら、第二例に進んでください。)

list1 = [1, 2, 3] 
list2 = [(i, i*2, i) for i in list1] 
# list2 = [(1, 2, 1), (2, 4, 2), (3, 6, 3)] 

がフラットなリストを取得するには、次のリストの途中で値をインクリメント :

list1 = [1, 2, 3] 
tmp = [(i, i*2) for i in list1] 
list2 = [] 
map(list2.extend, tmp) 
# list2 = [1, 2, 1, 2, 4, 2, 3, 6, 3] 

編集を理解はまだ変わっています。実際に行う必要がある場合は、定期的なforループを作成して、値を追加する方がよいでしょう。 Pythonでは、そのような巧妙さは、ほとんどいつも "unpythonic"とブランド化されています。もしあなたがそうしなければならないのですが、このようなフォーラムでは、あなたはフラークの終わりはありません。 ;)

+0

基本的には、リストの理解の範囲外の値を増やす必要があります。 –

+0

"for item in list1"ループとして何をしているのか記述できますか?そのようにリストの理解に適しているかどうかを判断することは簡単になります。 – ojrac

0

あなたは複数の文を行うことはできませんが、関数呼び出しを行うことができます。あなたは上記の望むように見えるものを行うには、あなたができる:一般的に

list1 = ... 
list2 = [ (sum(list1[:i], i) for i in list1 ] 

を、リストの内包表記は、Pythonの「機能」部分の一部なので、あなたに...機能制限しています。他の人々は、必要に応じて独自の関数を書くことができると示唆しており、これも有効な提案です。

+0

これはn個のリストを生成しません.nは最初のリストの長さですか?その結果、リストが何千もの要素であった場合、時間がかかりすぎる可能性があります。 –

+0

確かに、効率は目標ではありませんでした - リストの理解を使用していました。あなたの発電機ソリューションははるかに効率的です。 – pjz

1

currentValue += sum(list1) 

か:

for x in list1: 
    currentValue += x 

リストの内包表記は素晴らしいです、私は彼らを愛し、しかし謙虚なforループと間違って何もない、あなたはshouldn

EDIT: "しかし、収集した値と異なる値を増やしたいのですが?"

あなたは何で増分しますか?あなたはあなたのコマンドでパイソンの全力を持っています!

x平方のインクリメント?

for x in list1: 
    currentValue += x**2 

xの一部の関数とリスト内の位置によって増分されますか?

for i, x in enumerate(list1): 
    currentValue += i*x 
+0

しかし、収集した値と異なる値を増やしたいのですが? –

1

なぜ重複するリストを作成しますか?リストの理解は、コンテンツの合計だけであるように思えます。

どうしてですか。

list2 = list(list1) #this makes a copy 
currentValue = sum(list2) 
2

pjzはあなたがカウンタ値を追跡するためにクロージャを使用することができますので、ここで、関数を使用することができ、言ったように:

# defines a closure to enclose the sum variable 
def make_counter(init_value=0): 
    sum = [init_value] 
    def inc(x=0): 
     sum[0] += x 
     return sum[0] 
    return inc 

次に、あなたがリスト1でやりたい:

list1 = range(5) # list1 = [0, 1, 2, 3, 4] 
そして今、たった2行で、我々が得るLIST2:

counter = make_counter(10) # counter with initial value of 10 
list2 = reduce(operator.add, ([counter(x), x] for x in list1)) 
最終的には

、リスト2は含まれています

[10, 0, 11, 1, 13, 2, 16, 3, 20, 4] 

あなたが望んでいる、とあなたは1回の呼び出しでループした後、カウンタの値を取得することができた。最後に

counter() # value is 20 

、あなたは置き換えることができますあなたが望むどんな種類の操作でもクロージャのものは、ここでは増分がありますが、それは本当にあなた次第です。 注意はまた、我々はLIST2を平らにするために削減し、この小さなトリックを減らすの行を呼び出す前オペレータをインポートする必要が使用することを:

import operator 
関連する問題