Reputation: 5974
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
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