Paul
Paul

Reputation: 5974

Condition in lambda?

I have code that compares neighbouring lists, the second element of each list being added to it's neighbours second element if the third element of each list is 1. The code then finds the lowest of these summed pairs, and finally the lowest second element of this pair. However now I want to ignore cases where the first element of each pair is the same, such as the first two lists below.

aList = [[10564, 15, 1], [10564, 13, 1], [10589, 18, 1], [10637, 39, 1], [10662, 38, 1], [10837, 1, 1], [3, 17, 13], [7, 21, 13], [46, 26, 13]]

import sys
from operator import itemgetter
from itertools import tee, izip,ifilter

def pairwise(iterable):
    #"s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

def neighbouring_minimum(iterable):
    paired = pairwise(iterable)

    # find minimum pair by second elements summed
    minpair = min(paired, key=lambda pair: pair[0][1] + pair[1][1])  
    return min(minpair, key=itemgetter(1))

filtered = ifilter(lambda x: x[2] == 1, aList)
print neighbouring_minimum(filtered)

I am new to lambda, if I change

minpair = min(paired, key=lambda pair: pair[0][1] + pair[1][1])  

to this code below, is this the correct functionality, and is there a cleaner way to write this?

minpair = min(paired, key=lambda pair: pair[0][1] if (pair[0][0] != pair[1][0]) else pair[0][1] + pair[1][1] )  

Upvotes: 1

Views: 474

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122312

You have your logic inverted; you are returning pair[0][1] if the first elements of the pair are unequal. Invert the condition:

minpair = min(paired, key=lambda pair: pair[0][1] if pair[0][0] == pair[1][0] else pair[0][1] + pair[1][1])  

But, do note that the summed pairs are likely to be greater in value than any single value is going to be. For your example, your logic would return 15, which is definitely lower than any other neighbour sum you generate for your example input:

>>> map(lambda pair: pair[0][1] if pair[0][0] == pair[1][0] else pair[0][1] + pair[1][1], pairwise(aList))
[15, 31, 57, 77, 39, 18, 38, 47]

The above sample shows you what values the lambda generates, and 15 would win as the minimum, hands down.

To ignore pairs where the first element is the same, you should instead return float('inf'):

minpair = min(paired, key=lambda pair: pair[0][1] + pair[1][1] if pair[0][0] != pair[1][0] else float('inf'))  

float('inf') (positive infinity) is always going to be higher than any summed pair, so min() will not consider that specific pair.

Now the output is:

>>> map(lambda pair: pair[0][1] + pair[1][1] if pair[0][0] != pair[1][0] else float('inf'), pairwise(aList))
[inf, 31, 57, 77, 39, 18, 38, 47]

and the pair totalling 18 will be picked.

Upvotes: 2

Related Questions