2017-12-30 44 views
0

これをforループをネストされたif文を使ってリスト内包に変換するにはどうすればよいですか?リスト内包Pythonのネストされた制御フロー

stock = [] 
for i in range(10): 
    if i <= 5: 
     trade = "buy" 
    elif i > 5 and i <= 7: 
     trade = "hold" 

     if i == 6: 
      trade = "short-sell" 

    else: 
      trade = "sell" 
    stock.append(trade.capitalize()) 
stock 

[ '購入'、 '購入'、 '購入'、 '購入'、 '購入'、 '購入'、 '短期売り'、 'ホールド'、 '売る'、 '売る']

私がこれまで持っている最高のは、次のとおりです。

["Buy" if i <= 5 else "Hold" if i > 5 and i <= 7 else "Sell" 
for i in range(10)] 

[ '購入'、 '購入'、 '購入'、 '購入'、 '購入' 、 '購入する'、 '保留する' 、 '保留'、 '売る'、 '売る']

ご協力いただければ幸いです。 :)

+2

短い方が良いとは限りません。 FOR/IFコードは、特にある時点で他のプログラマーがそれを読まなければならない場合には、読みやすくなります。 – Ctznkane525

+0

良い点はJohnですが、一般的に短いコードほど速くなる傾向があります。 – MichaelRSF

+0

私はエラーを修正しました、それはちょうど株式です。append(trade.capitalize())は正しくインデントされませんでした。 – MichaelRSF

答えて

2

あなたはi == 6ケースがありません。

["Buy" if i <= 5 else "Short-sell" if i == 6 else "Hold" if i <= 7 else "Sell" for i in range(10)] 

を試してみて、これはしかし、このようにそれを行うには十分な理由が本当にありません、私たちに

['Buy', 'Buy', 'Buy', 'Buy', 'Buy', 'Buy', 'Short-sell', 'Hold', 'Sell', 'Sell'] 

を与えます。読むのは簡単ではなく、あなたが見たように、間違いを見落とすのは簡単です。私があなただった場合、私はあなたの元のパターンに固執するでしょう(あなたはここに掲載のコードはいえ、かなりの仕事をしません)。ここ

+0

ありがとう、私はそれを受け入れますが、それはネストされたifステートメントと同等ではなく、ネストされていない別のelifステートメントです。 – MichaelRSF

+0

これらは論理的に同等です。入れ子にされた 'if'ステートメントを本当に望むなら、i> 5ならi <= 7なら'( 'i' = 6ならば 'ショート・セール'、それ以外なら 'ホールド')を使うことができます。 –

+0

'i <= 7' 「i == 7」とする。 –

2

は、あなたの様々な条件文と等価な式です:アクションで

['buy' if i <=5 else (('short-sell' if i == 6 else 'hold') if i > 5 and i <= 7 else 'sell') for i in range(10)] 

if i == 6: 
    trade = "short-sell" 
else: 
    trade = "hold" 
In [10]: ['buy' if i <=5 else (('short-sell' if i == 6 else 'hold') if i > 5 and i <= 7 else 'sell') for i in range(10)] 
Out[10]: 
['buy', 
'buy', 
'buy', 
'buy', 
'buy', 
'buy', 
'short-sell', 
'hold', 
'sell', 
'sell'] 

注意が、このケースでは、あなたのネストされたifステートメントは同等です

このような、ネイティブの条件付き式を使用しないでください。これは、コードレビューでは、あなたを励ますようなものです。 forループを使うだけです。あなたが理解を使用するために燃える願望を持っている場合は、完全入れ子の条件文を使用して機能に条件ロジックを入れて、何かのように:

In [14]: def f(i): 
    ...:  if i <= 5: 
    ...:   trade = "buy" 
    ...:  elif i > 5 and i <= 7: 
    ...:   trade = "hold" 
    ...: 
    ...:   if i == 6: 
    ...:    trade = "short-sell" 
    ...: 
    ...:  else: 
    ...:   trade = "sell" 
    ...:  return trade 
    ...: 

In [15]: [f(i) for i in range(10)] 
Out[15]: 
['buy', 
'buy', 
'buy', 
'buy', 
'buy', 
'buy', 
'short-sell', 
'hold', 
'sell', 
'sell'] 
0

あなたが本当にリストの内包を行いたい場合は

>>> ["Buy"*(i<=5) + "hold"*(i == 7) + "short-sell"*(i == 6) + "sell"*(i > 7) for i in range(10)] 
['Buy', 'Buy', 'Buy', 'Buy', 'Buy', 'Buy', 'short-sell', 'hold', 'sell', 'sell'] 
ここ
1

は非常に異なったアプローチです:

action_tests = [ 
    ('buy', lambda x: x <= 5), 
    ('hold', lambda x: (5 < x <= 7) and (x != 6)), 
    ('short-sell', lambda x: x == 6), 
] 

stock = [next((action for action, test in action_tests if test(i)), 'sell') for i in range(10)] 

「それ以外」の条件は、そのいずれも場合にnextのデフォルト値によって処理されますaction_testsのテストはtrueを返します。

メンテナンス性を悪化させるため、複雑なロジックをすべて1つの行に絞り込むことは本当に望ましくありません。バグを検出するのは難しいでしょうし、スペック変更。

このアプローチは、ifという文が簡単に拡張可能であるとすれば、元のセットよりも改善されています...単に新しい機能をaction_testsに適切な優先順位で追加するだけで、理解はまだ機能します! ifブランチを再加工する必要はなく、新しいアクションのサポートを追加したいときには、1行だけを追加する必要があります。

+0

うわー、それは本当にあなたが唯一の文を使用して涼しいです。リストの理解に限界があるかどうかを知りたかったので、理解してもらいました。ありがとう! – MichaelRSF

関連する問題