Python 如何根据嵌套列表中内部列表的第一个元素获取所有最小元素?
简单地说!这里有一个列表,上面写着Python 如何根据嵌套列表中内部列表的第一个元素获取所有最小元素?,python,list,minimum,Python,List,Minimum,简单地说!这里有一个列表,上面写着LST=[[12,1],[23,2],[16,3],[12,4],[14,5],我想根据列表内部的第一个元素得到这个列表的所有最小元素。因此,对于上述示例,答案是[12,1]和[12,4]。python中有什么典型的方法可以做到这一点吗? 提前感谢您。两张通行证: m = min(LST, key=operator.itemgetter(0))[0] print [x for x in LST if x[0] == m] minval = min(LST)[0
LST=[[12,1],[23,2],[16,3],[12,4],[14,5]
,我想根据列表内部的第一个元素得到这个列表的所有最小元素。因此,对于上述示例,答案是[12,1]
和[12,4]
。python中有什么典型的方法可以做到这一点吗?
提前感谢您。两张通行证:
m = min(LST, key=operator.itemgetter(0))[0]
print [x for x in LST if x[0] == m]
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))
def all_minima(iterable,key=None):
如果key为None:key=id
hasminvalue=False
最小值=无
minlist=[]
对于iterable中的条目:
值=键(条目)
如果不是hasminvalue或value
一个紧凑的单遍解决方案需要对列表进行排序——从技术上讲,这是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
,即操作符。itemgetter(0)
,是一个关键函数,用于选择参数的第一项进行排序-操作符的目的就是要轻松、紧凑地构建此类函数
sorted(lol,key=f)
因此返回列表的排序副本lol
,按增加第一项排序。如果省略key=f
,则排序后的副本将按字典顺序排列,因此也将按增加第一项的顺序排列,但这仅起“主键”的作用——具有相同第一子项的项将依次按其第二子项的值在它们之间排序,以此类推——当使用key=f
时,保证在具有相同第一个子项的项目之间保持原始顺序。您没有指定您需要的行为(在您的示例中,这两种行为恰好产生相同的结果,因此我们无法与该示例区分),这就是为什么我会仔细详细说明这两种可能性,以便您可以选择
itertools.groupby(sorted(lol,key=f,key=f)
执行作为操作核心的“分组”任务:它根据key
排序标准从序列中生成组(在本例中,序列sorted
提供)。也就是说,当您调用f
时,所有相邻项之间产生相同值的组(以该项为参数),然后是所有相邻项产生与第一个组不同值的组(但它们之间相同),依此类推groupby
尊重它作为参数的序列的顺序,这就是为什么我们必须首先对lol
进行排序(而groupby
的这种行为使得它在序列顺序确实重要的许多情况下非常有用)
由groupby
编辑的每个结果yield
是一对k,g
:一个键k
,它是组中每个项目的f(i)
结果,一个迭代器g
,它按顺序生成组中的每个项目
给定迭代器的next
内置(此解决方案中唯一需要Python2.6的部分)将生成其下一项——特别是在新生成的迭代器上调用时的第一项(当然,每个生成器都是迭代器,就像groupby
的结果一样)。在早期的Python版本中,它必须是groupby(…).next()
(因为next
只是迭代器的一种方法,而不是内置的),它从2.6版开始就被弃用了
总之,我们的next(…)
的结果正好是k,g
对,其中k
是第一个子项的最小值(即排序后的第一个值),而g
是组项的迭代器
因此,使用该[1]
我们只选择迭代器,因此我们有一个迭代器,只生成我们想要的子项
因为我们需要的是列表,而不是迭代器(根据您的规格),所以最外层的list(…)
调用完成了任务
就性能而言,所有这些都值得吗?不在您给出的小示例列表中--最小值实际上比@Kenny答案中的任一代码都慢(其中第一个“两通”解决方案更快)。我只是认为有必要记住您可能遇到的下一个序列处理问题的想法,其中典型输入的细节可能会有很大的不同(更长的列表、更少的极小值、输入中的偏序、&c、&c;-)。这是一个常见的问题。请搜索。@SLott:你的链接问题与OP的问题完全不同。@KennyTM:怎么回事?他们看起来和我一模一样。我错过的区别是什么?@SLott:谢谢你指向链接。不幸的是,正如我所看到的,这是无关紧要的。
import itertools
import operator
f = operator.itemgetter(0)
def minima(lol):
return list(next(itertools.groupby(sorted(lol, key=f), key=f))[1])