【问题标题】:How to get all the minimum elements according to its first element of the inside list in a nested list?如何根据嵌套列表中内部列表的第一个元素获取所有最小元素?
【发布时间】:2011-04-02 00:26:15
【问题描述】:

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

【问题讨论】:

  • stackoverflow.com/questions/3259159/sorting-a-list-of-tuples 这是一个常见问题。请搜索。
  • @SLott:您的链接问题与 OP 的问题完全不同。
  • @KennyTM:怎么会这样?他们看起来和我一模一样。我错过了什么区别?
  • @SLott:感谢您提供链接。不幸的是,正如我所见,这无关紧要。

标签: python list minimum


【解决方案1】:

两遍:

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

【讨论】:

    【解决方案2】:

    一个紧凑的单通道解决方案需要对列表进行排序——从技术上讲,O(N log N) 是一个 N-long 列表,但是 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) 因此返回列表列表lol 的排序副本,按增加第一项排序。如果您省略key=f,则排序后的副本将按字典顺序排序,因此将按照增加第一项的顺序,但这仅充当“主键”-具有相同的项第一个子项将依次按第二个子项的值在它们之间进行排序,依此类推——而 with key=f 您保证在项目之间保留原始顺序具有相同的第一个子项。您没有指定您需要哪种行为(在您的示例中,这两种行为恰好产生相同的结果,因此我们无法与该示例区分开来),这就是为什么我要仔细详细说明这两种可能性,以便您选择。

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

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

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

    所以,总而言之,我们的next(...) 的结果正是k, g 对,其中k 是第一个子项的最小(即排序后的第一个)值,g 是一个迭代器用于组的项目。

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

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

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

    【讨论】:

      【解决方案3】:
      m = min(LST, key=operator.itemgetter(0))[0]
      print [x for x in LST if x[0] == m]
      

      【讨论】:

        【解决方案4】:
        minval = min(x[0] for x in LST)
        result = [x for x in LST if x[0]==minval]
        

        【讨论】:

          猜你喜欢
          • 2021-03-11
          • 2021-04-21
          • 1970-01-01
          • 2014-11-06
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多