12

我有一个这样的列表列表:

[[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]在每个列表中,仅当 element[0] 超过 10000 等时。我该怎么做?我试过了,目前只能比较同一列表中的元素,这不是我想要的。在我提到的情况下,我将返回 [10787, 9] 但如果有另一个超过 10000 的值 9 我也想返回它。

4

5 回答 5

14

这取决于您想要输出的内容。首先,您需要根据“范围” 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)]

如果您确定将有少于匹配项,则可以使用andN更有效地执行此操作。在您不知道匹配数上限的一般情况下,我认为这种解决方案更好(与 O(NlogN) 的排序相比,它是 O(N))。heapqitertools.takewhile


1注意“生成器表达式”在用完之前只能迭代一次

于 2013-04-16T12:24:33.920 回答
4
>>> l=[[10564, 15], [10564, 13], [10589, 18], [10637, 39]]
>>> min(x[1] for x in l if x[0] > 10000)
13
>>>

更新您的评论(您可以在 min 函数中使用 lambda 作为 key,在大型列表中使用 itemgetter 更快):

>>> min((x for x in l if x[0] > 10000), key=lambda k:k[1])
[10564, 13]
于 2013-04-16T12:26:03.540 回答
4

这是一种非常简单的方法,它只找到最小值,然后根据该值构建列表。

>>> 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]
于 2013-04-16T12:29:37.600 回答
2

如果您需要多个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]......

于 2013-04-16T12:46:17.840 回答
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]]

print min(map(lambda y: y[1] ,filter(lambda x: x[0]>10000,a)))
于 2013-04-16T12:24:14.773 回答