минимум списка списков

У меня есть список списков, как так:

[[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]]

Я пытаюсь найти наименьшее значение для второго элемента в каждом списке (поэтому сравните 15-13-18 и т. д. не сравнивая 10564 и 15 ), но также разделить его на диапазоны, чтобы я мог сказать, самый низкий второй элемент[1] в каждом списке, только если элемент[0] превышает 10000 и т. д. Как мне это сделать? Я попробовал и могу сравнить только элементы в том же списке, что и сейчас, что не то, что я хочу. В случае, если я упоминаю, что я тогда вернусь [10787, 9] но если бы было другое значение более 10000 с 9, я бы тоже хотел вернуть его.

5 ответов


это зависит от того, что вы хотите для выхода. Во-первых, вам нужно будет отфильтровать свой список на основе "диапазонов" 1

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

на if условие может быть настолько сложным, насколько вы хотите (в пределах допустимого синтаксиса). например:

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

это прекрасно.


теперь, если вы хотите только второй элемент подсписка:

min(x[1] for x in gen)

конечно, вы можете встроить все это:

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

если вы хочу весь подсписок:

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

пример:

>>> 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]

к сожалению, это только даст вам первый подсписок, который соответствует критериям. Чтобы получить их все:

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)]

если вы точно знаете, что будет меньше, чем N матчи, Вы могли бы сделать это немного более эффективно с heapq и itertools.takewhile. В общем случае, когда вы не знаете верхнего предела количества матчей, я думаю, что это решение лучше (Это O(N) по сравнению с сортировкой, которая является O (NlogN)).


1обратите внимание, что" выражение генератора " может быть повторено только один раз, прежде чем он будет исчерпан


вот очень простой подход, который просто находит минимальное значение, а затем строит список на основе этого значения.

>>> a = [[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]]
>>> a_min = min(i[1] for i in a)
>>> [i[0] for i in a if i[1] == a_min and i[0] > 10000] + [a_min]
[10787, 9]

код правильно отображает несколько значений:

>>> a += [[10391, 9]] #add another pair with a first value > 10000
>>> [i[0] for i in a if i[1] == a_min and i[0] > 10000] + [a_min]
[10787, 10391, 9]

Если вам требуется несколько mins, тогда, возможно, вам лучше всего фильтровать применимые элементы и сортировать их...

vals = sorted((el for el in your_list if el[0] >= 10000), key=lambda L: L[1])
# [[10787, 9], [10812, 12], [10564, 13], [10762, 14], [10564, 15], [10737, 15], [10589, 18], [10662, 38], [10637, 39], [10837, 45], [10712, 50]]

тогда вы можете взять vals[0] получить первый, vals[1] чтобы получить второй, или использовать нарезку, такую как vals[:5]...


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

обновление для вашего комментария (вы можете использовать лямбда для ключа в функции min, itemgetter немного быстрее в больших списках):

>>> min((x for x in l if x[0] > 10000), key=lambda k:k[1])
[10564, 13]

a=[[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]]

print min(map(lambda y: y[1] ,filter(lambda x: x[0]>10000,a)))