2016-10-19 10 views
0

Python lambdaを使用すると、要素が(マップの)別のリストに存在するかどうかを確認し、変数を増やすことができますか?私はラムダを使って自分のコードを最適化/リファクタリングしようとしていますが、私は行って自分自身を混乱させました。リストとインクリメントを検索するラムダ

以下は、ラムダに変換する既存のコードです。 1つのラムダを使用してこれを行うことは可能ですか、2つのラムダを使用する必要がありますか?任意のアドバイスどのようにラムダ/ sに変換することができますか?

current_orders = auth.get_orders() 
# returns [{'id': 'foo', 'price': 1.99, ...}, ...] 

deleted_orders = auth.cancel_orders() 
# returns id's of all cancelled orders [{'id': 'foo'}, {'id': 'bar'}, ...] 


# Attempting to convert to lambda 
n_deleted = 0 
for del_order in deleted_orders: 
    for order in current_orders: 
     if del_order['id'] == order['id']: 
      n_deleted += 1 

# lambda 
n_deleted = filter(lambda order, n: n += order['id'] in current_orders, deleted_orders) 
# end 


if n_deleted != len(orders): 
    logger.error("Failed to cancel all limit orders") 

注:私はif len(deleted_orders) < len(current_orders): logger.error("Failed to delete ALL orders")を言うことができます知っているが、私は...: logger.error("Failed to delete ORDER with ID: %s")

+2

「ラムダ」は、単純な1行の関数を実装するために設計されています。関数を終了させるために1行以上必要な場合は、 'def'を使って関数を作成してください。 –

+1

理想的には 'lambda'関数は副作用を持ってはいけません –

答えて

1

その周りにハックすることが可能であるが、lambda sが変異してはならない、彼らは返す必要がありますを言って、結局私のラムダを展開したいです新しい結果。あなたがlambda秒overcomplicateてはならない。また、彼らはあなたがすべてでlambda+=(または任意の種類の割り当て)を使用し、サイド用filterを使用することはできませんsort方法

+0

本当ですが、私は2ラムダでこれを行うことができると思いますか? 'a 'がtrue/1を返す場合、同じ' id 'のマップの2つのリストを検索するためのラムダ(a)つまり、ラムダを巣に入れますか? –

+1

@ JakeM: 'lambda'sは限定された目的の無名関数です。彼らは非常に多くを行うことができますが、それらは限られており、醜いです、そして、通常、与えられた問題を解決する最悪の方法です。あなたはハンマーを持っており、あなたは爪のようにすべてを扱っています。正しい方法で問題を解決し、それを馬鹿馬鹿しく畳み込まれた 'ラムダ '解に収めようとしないでください。 – ShadowRanger

3

ためkeyような短い迅速な機能のために意図されています-effectsはひどいアイディアです(このパターンはreduceのようなものですが、何をしようとしているのかは分かりません)。

order['id']の数値がcurrent_ordersに表示された回数をカウントしようとしているようです。このためにはlambdaを使用しないでください。効率を向上させるために、setようにしてからid Sを取得し、すべてのid sが両方listで発見されたかどうかをチェックするためにset操作を使用:あなたが知りたい場合は

from future_builtins import map # Only on Py2, to get generator based map 
from operator import itemgetter 


... rest of your code ... 

getid = itemgetter('id') 
# Creating the `set`s requires a single linear pass, and comparison is 
# roughly linear as well; your original code had quadratic performance. 
if set(map(getid, current_orders)) != set(map(getid, deleted_orders)): 
    logger.error("Failed to cancel all limit orders") 

注文はキャンセルされませんでした、とifチェックしてlogger出力を交換するわずかな微調整は、:あなたがoid順エラーログが必要な場合

for oid in set(map(getid, current_orders)).difference(map(getid, deleted_orders)): 
    logger.error("Failed to cancel order ID %s", oid) 

、ラップsortedで呼び出し、あなたはcurrent_ordersで返されるのと同じ順序でそれをしたい場合は、に変更します。おそらくあなたは、リストの内包表記を使用する必要があります

from itertools import filterfalse # On Py2, it's ifilterfalse 

# Could inline deletedids creation in filterfalse if you prefer; frozenset optional 
deletedids = frozenset(map(getid, deleted_orders)) 
for oid in filterfalse(deletedids.__contains__, map(getid, current_orders)): 
    logger.error("Failed cancel order ID %s", oid) 
1

。例えば、

current_order_ids = {order['id'] for order in current_orders} 
not_del = [order for order in deleted_orders if order['id'] not in current_order_ids] 

for order in not_del: 
    logger.error("Failed to delete ORDER with ID: %s", order['id']) 
+0

私はあなたがそれを後方に持っていると思います。OPはキャンセルされなかった現在の注文に興味があります。注文は全くキャンセルされていません。(どちらもエラーと思われます。また、大括弧を括弧に変えてlistcompをスキップし、一時的な 'list'を避けるためにgenexprを使用することもできます(結果は一度しか反復されないと仮定します)。 – ShadowRanger

関連する問題