Lambda that searches list and increments
<p>Using a Python <code>lambda</code> can you check whether an element exists in another list (of maps) and also increment a variable? I'm attempting to optimise/refactor my code using a lambda but I've gone and confused myself.</p>

<p>Below is my existing code that I want to convert to a lambda. Is it possible to do this using one lambda or will I need to use 2 lambdas? Any advice how can I convert it to a lambda/s?</p>

<pre><code>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")
</code></pre>

<p><em>Note:</em> I know I can say <code>if len(deleted_orders) &lt; len(current_orders): logger.error("Failed to delete ALL orders")</code> but I want to expand my lambda eventually to say <code>...: logger.error("Failed to delete ORDER with ID: %s")</code></p>

<p>You can't use <code>+=</code> (or assignment of any kind) in a <code>lambda</code> at all, and using <code>filter</code> for side-effects is a terrible idea (this pattern looks kind of like how <code>reduce</code> is used, but it's hard to tell what you're trying to do).</p>

<p>It looks like you're trying to count how many <code>order['id']</code> values appear in <code>current_orders</code>. You shouldn't use a <code>lambda</code> for this at all. To improve efficiency, get the <code>id</code>s from out as a <code>set</code> and use <code>set</code> operations to check if all the <code>id</code>s were found in both <code>list</code>:</p>

<pre><code>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")
</code></pre>

<p>If you want to know <em>which</em> orders weren't canceled, a slight tweak, replacing the <code>if</code> check and <code>logger</code> output with:</p>

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

<p>If you want the error logs ordered by <code>oid</code>, wrap the <code>set.difference</code> call in <code>sorted</code>, if you want it in the same order returned in <code>current_orders</code>, change to:</p>

<pre><code>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)
</code></pre>

python lambda