Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

minimum of list of lists

Tags:

python

list

min

I have a list of lists like so:

[[10564, 15], [10564, 13], [10589, 18], [10637, 39], [10662, 38], [10712, 50], [10737, 15], [10762, 14], [10787, 9], [10812, 12], [10837, 45], [3, 17], [7, 21], [46, 26], [48, 12], [49, 24], [64, 14], [66,
 17], [976, 27], [981, 22], [982, 22], [983, 17], [985, 13], [517, 9], [521, 15], [525, 11], [526, 13], [528, 14], [698, 14], [788, 24], [792, 19]]

I am trying to find the lowest value for the second element in each list(so compare 15 to 13 to 18 etc not comparing 10564 and 15 ), but also to separate it into ranges, so I could say, lowest second element[1] in each list, only if element[0] is over 10000 etc. How might I do this? I tried it and can only compare elements in the same list as of yet, which is not what I want. In the case I mentions I would then be returning [10787, 9] but if there was another value over 10000 with 9 I would want to return that also.

like image 361
Paul Avatar asked Apr 16 '13 12:04

Paul


2 Answers

This depends on what you want for output. First, you'll need to filter your list based on the "ranges" 1

gen = (x for x in lists if x[0] > 10000)

The if condition can be as complicated as you want (within valid syntax). e.g.:

gen = (x for x in lists if 5000 < x[0] < 10000)

Is perfectly fine.


Now, If you want only the second element from the sublists:

min(x[1] for x in gen)

Of course, you could inline the whole thing:

min(x[1] for x in lists if x[0] > 10000)

If you want the entire sublist:

from operator import itemgetter
min(gen,key=itemgetter(1))

example:

>>> lists = [[10564, 15], [10564, 13], [10589, 18], [10637, 39], [10662, 38], [10712, 50], [10737, 15], [10762, 14], [10787, 9], [10812, 12], [10837, 45], [3, 17], [7, 21], [46, 26], [48, 12], [49, 24], [64, 14], [66,17], [976, 27], [981, 22], [982, 22], [983, 17], [985, 13], [517, 9], [521, 15], [525, 11], [526, 13], [528, 14], [698, 14], [788, 24], [792, 19]]
>>> gen = (x for x in lists if x[0] > 10000)
>>> min(x[1] for x in gen)
9
>>> gen = (x for x in lists if x[0] > 10000)
>>> from operator import itemgetter
>>> min(gen,key=itemgetter(1))
[10787, 9]

Unfortunately, these only give you the first sublist which matches the criteria. To get all of them:

target = min(x[1] for x in lists if x[0] > 10000)
matches = [x for x in lists if (x[1] == target) and (x[0] > 10000)]

If you know for sure that there will be less than N matches, you could do this a little more efficiently with heapq and itertools.takewhile. In the general case where you don't know an upper limit on the number of matches, I think this solution is better (It's O(N) compared to sorting which is O(NlogN)).


1Note that the "generator expression" can only be iterated over once before it is exhausted

like image 124
mgilson Avatar answered Oct 12 '22 13:10

mgilson


>>> l=[[10564, 15], [10564, 13], [10589, 18], [10637, 39]]
>>> min(x[1] for x in l if x[0] > 10000)
13
>>>

update for your comment (you can use lambda for key in min function, itemgetter a little faster on large lists):

>>> min((x for x in l if x[0] > 10000), key=lambda k:k[1])
[10564, 13]
like image 37
ndpu Avatar answered Oct 12 '22 12:10

ndpu