3

简单的说!有这个列表说LST = [[12,1],[23,2],[16,3],[12,4],[14,5]],我想根据内部列表的第一个元素获取该列表的所有最小元素。所以对于上面的例子,答案是[12,1]and [12,4]。python中有没有这样做的典型方法?提前谢谢你。

4

4 回答 4

5

两次通行证:

minval = min(LST)[0]
return [x for x in LST if x[0] == minval]

一关:

def all_minima(iterable, key=None):
  if key is None: key = id
  hasminvalue = False
  minvalue = None
  minlist = []
  for entry in iterable:
     value = key(entry)
     if not hasminvalue or value < minvalue:
        minvalue = value
        hasminvalue = True
        minlist = [entry]
     elif value == minvalue:
        minlist.append(entry)
  return minlist

from operator import itemgetter
return all_minima(LST, key=itemgetter(0))
于 2010-08-21T10:09:04.047 回答
3

一个紧凑的单通道解决方案需要对列表进行排序——从技术上讲,这O(N log N)适用于一个N长列表,但是 Python 的排序非常好,而且很多序列“恰好”在其中嵌入了一些顺序(timsort巧妙地利用它来加快速度) ,基于排序的解决方案有时在现实世界中具有令人惊讶的出色性能。

这是一个需要 2.6 或更高版本的解决方案:

import itertools
import operator
f = operator.itemgetter(0)

def minima(lol):
  return list(next(itertools.groupby(sorted(lol, key=f), key=f))[1])

要理解这种方法,“从内向外”看会有所帮助。

f, 即 ,operator.itemgetter(0)是一个键函数,它选择其参数的第一项用于排序目的 - 的目的operator.itemgetter是轻松紧凑地构建此类函数。

sorted(lol, key=f)因此返回 list-of-lists 的排序副本,lol按增加第一项排序。如果您省略key=f排序后的副本,则将按字典顺序排序,因此它将按照增加第一项的顺序,但这仅充当“主键” - 具有相同第一个子项的项目将依次排序它们的第二个子项的值,依此类推——而key=f可以保证在具有相同第一个子项的项之间保留原始顺序。您没有指定您需要哪种行为(在您的示例中,这两种行为恰好产生相同的结果,因此我们无法与该示例区分开来),这就是为什么我要仔细详细说明这两种可能性,以便您选择。

itertools.groupby(sorted(lol, key=f), key=f)执行作为操作核心的“分组”任务:它根据排序标准从序列(在这种情况下,序列提供)中产生组。也就是说,当您使用项目作为参数调用时,所有相邻项目在它们之间产生相同值的组,然后在所有相邻项目中产生与第一组不同的值(但它们之间相同)的组,依此类推. 尊重它作为参数的序列的顺序,这就是为什么我们必须对第一个进行排序(这种行为使它在序列的顺序很重要的许多情况下非常有用)。sortedkeyfgroupbylolgroupby

每个由结果yield编辑的结果groupby是一对k, g:一个键k,它是f(i)组中每个项目的结果,一个迭代器g,它按顺序产生组中的每个项目。

给定迭代器的next内置(此解决方案中唯一需要 Python 2.6 的位)生成其下一项 - 特别是在新创建的迭代器上调用时的第一项(当然,每个生成器都是一个迭代器,正如groupby的结果)。在早期的 Python 版本中,它必须是groupby(...).next()(因为next它只是迭代器的一种方法,而不是内置的),自 2.6 以来已弃用。

因此,总而言之,我们的结果next(...)正是第一个子项的最小值(即排序后的第一个)值的对,并且k, g是组项的迭代器。kg

所以,[1]我们只选择迭代器,所以我们有一个迭代器,只产生我们想要的子项。

由于我们需要一个列表,而不是迭代器(根据您的规范),所以最外面的list(...)调用完成了这项工作。

这一切都值得吗,性能方面?不在您提供的小示例列表中-minima实际上比@Kenny 答案中的任何一个代码都慢(其中第一个“两次通过”解决方案更快)。我只是认为对于您可能遇到的下一个序列处理问题,值得牢记这些想法,其中典型输入的细节可能完全不同(更长的列表,更稀有的最小值,输入中的部分排序,&c,&c;-)。

于 2010-08-21T15:59:20.163 回答
2
m = min(LST, key=operator.itemgetter(0))[0]
print [x for x in LST if x[0] == m]
于 2010-08-21T10:02:15.890 回答
-1
minval = min(x[0] for x in LST)
result = [x for x in LST if x[0]==minval]
于 2010-08-21T10:06:56.297 回答