【问题标题】:How to split a list of tuples based on the minimum value in each tuple?如何根据每个元组中的最小值拆分元组列表?
【发布时间】:2021-08-31 09:14:58
【问题描述】:

假设我有一个元组列表(为方便起见,我将在示例中放入 6 个值),如下所示:

x = [(1,2,3), (2,3,1), (0,10,100), (4,0,5), (2,1,3), (3.3,9,1.2), (4.5,2,0), (2,4,10), (100, 10, 30)]

x 列表是一个元组列表,每个元组有 3 个值,所以只有 3 个索引。

我想要的是将列表x拆分为3个列表,第一个列表在第一个索引的元组中具有最小值,第二个列表在第二个索引的元组中具有最小值,第三个list 在第三个索引处具有元组的最小值。基本上,我需要输入每个元组,看看最小值在哪里(在哪个索引处),并将元组放在它所属的子列表中。

所以我会得到这样的结果:

x1 = [(1,2,3), (0,10,100), (2,4,10)]
x2 = [(4,0,5), (2,1,3), (100, 10, 30)]
x3 = [(2,3,1), (3.3,9,1.2), (4.5,2,0)]

【问题讨论】:

    标签: python tuples


    【解决方案1】:

    简单检查的列表理解可以为您提供所需的输出:

    x = [(1,2,3), (2,3,1), (0,10,100), (4,0,5), (2,1,3), (3.3,9,1.2), (4.5,2,0), (2,4,10), (100, 10, 30)]
    
    x1 = [i for i in x if i[0] == min(i)]
    x2 = [i for i in x if i[1] == min(i)]
    x3 = [i for i in x if i[2] == min(i)]
    

    【讨论】:

    • 这不会是 O(3*n) 即我们需要循环整个列表 3 次吗?
    • @CutePoison O(3*n) == O(n)
    • 当然,但你仍然需要循环列表 3 次(这是我的“伪”O 观点)
    【解决方案2】:

    您可以简单地循环执行:

    import numpy as np
    x = [(1,2,3), (2,3,1), (0,10,100), (4,0,5), (2,1,3), (3.3,9,1.2), (4.5,2,0), (2,4,10), (100, 10, 30)]
    Xs = {0:[],1:[],2:[]} #For indexing 
    
    
    for t in x:
        idx = np.argmin(t)
        Xs[idx].append(t)
    
    x1 = Xs[0]
    x2 = Xs[1]
    x3 = Xs[2]
    

    【讨论】:

      【解决方案3】:

      一种使用collections.defaultdict的方式:

      from collections import defaultdict
      
      d = defaultdict(list)
      
      def argmin(arr):
          return min(range(len(arr)), key=lambda x: arr[x])
      
      for t in x:
          d[argmin(t)].append(t)
      

      或者使用numpy.argmin:

      for i, t in zip(np.argmin(x, 1), x):
          d[i].append(t)
          
      

      输出:

      defaultdict(list,
                  {0: [(1, 2, 3), (0, 10, 100), (2, 4, 10)],
                   2: [(2, 3, 1), (3.3, 9, 1.2), (4.5, 2, 0)],
                   1: [(4, 0, 5), (2, 1, 3), (100, 10, 30)]})
      

      【讨论】:

        【解决方案4】:

        您可以使用列表推导轻松做到这一点:

        abc = [(1,2,3), (2,3,1), (0,10,100), (4,0,5), (2,1,3), (3.3,9,1.2), (4.5,2,0), (2,4,10), (100, 10, 30)]
        
        
        x1 = [x for x in abc if x.index(min(x))==0]
        x2 = [x for x in abc if x.index(min(x))==1]
        x3 = [x for x in abc if x.index(min(x))==2]
        
        print(x1)
        print(x2)
        print(x3)
        
        Output:
        [(1, 2, 3), (0, 10, 100), (2, 4, 10)]
        [(4, 0, 5), (2, 1, 3), (100, 10, 30)]
        [(2, 3, 1), (3.3, 9, 1.2), (4.5, 2, 0)]
        

        【讨论】:

          【解决方案5】:
          def meth(a):
              if a[0] < a[1] and a[0] < a[2]:
                  return 1
              if a[0] > a[1] and a[0] < a[2]:
                  return 0
              return -1
          x = sorted(x, key=meth)
          print(x[:3])
          print(x[3:6])
          print(x[6:9])
          

          【讨论】:

          • 例如,如果x = [(1,2,3), (2,3,1)] 会给出错误的结果(基本上对于与问题中的不同的任何其他列表大小)
          【解决方案6】:

          您可以在没有导入的情况下执行此操作,只需对输入列表进行一次传递。

          • 用三个空子列表初始化结果列表。
          • 传递每个元组,并将其附加到元组中最小元素的匹配索引中的子列表中。
          • 最后,每个子列表将包含最小元素与子列表在同一索引中的元组:
          x = [(1,2,3), (2,3,1), (0,10,100), (4,0,5), (2,1,3), (3.3,9,1.2), (4.5,2,0), (2,4,10), (100, 10, 30)]
          
          mins = [[], [], []]
          for tup in x:
              mins[tup.index(min(tup))].append(tup)
          
          print(mins)
          

          将给予:

          [[(1, 2, 3), (0, 10, 100), (2, 4, 10)],    # mins[0] - tuples with minimum in index 0
           [(4, 0, 5), (2, 1, 3), (100, 10, 30)],    # mins[1] - tuples with minimum in index 1
           [(2, 3, 1), (3.3, 9, 1.2), (4.5, 2, 0)]]  # mins[2] - tuples with minimum in index 2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-10-20
            • 2012-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-01
            • 2014-04-27
            相关资源
            最近更新 更多