【问题标题】:Sorting a list containing lists对包含列表的列表进行排序
【发布时间】:2012-07-07 00:30:37
【问题描述】:

我有一种算法可以生成一个包含未知数量子列表的列表,每个子列表都有未知数量的字符串元素和一个浮点数。我需要根据这个浮动在主列表中排序这些子列表。此外,子列表中的字符串顺序不会被重新排列。

我目前正在运行一段代码(链接如下),它使用字典对其进行排序。如您所见,我收到了 KeyErrors。我以前没有使用过 dicts,所以我不知道从哪里开始。如果有更好的方法,那么我也对此持开放态度。 http://ideone.com/wr8UA

浮动不是连续的,我不确定使用我拥有的方法这有多大意义。意思是,偶尔会跳过数字(在 Ideone 的示例列表中,它们是 1.0、2.0、4.0;跳过 3.0 以在运行时模拟这种情况)。它们也不在子列表中的任何特定位置,因此所有 for 循环都在搜索它们。

希望这很清楚,我之前尝试过询问它并得到了反对意见,而不是关于让人们感到困惑的问题。让我知道是否有问题。谢谢大家!

编辑:根据要求在正文中编写代码:

listed = [ ["1 NWZ", "1 RWZ", "2 NWZ", "2 RWZ", "1E HZ", "1W HZ", "1-2EHZ", 2.0, "2W HZ"],
["1 NWZ", "1W HZ", "3E FZ", "SNOK", "POK", 3.0, "1-2EHZ", "2E AK", "2W HZ"],
["1 BW", "1AW AS", "3E FZ", "1BWAK", "POK", "TESTK", "1-2EHZ", "2E AK", 1.0]] 

dictionary={}
for sub_list in listed:
    for value in sub_list:
        if isinstance(value,float):
            dictionary[str(value)]=sub_list
        else:
            pass
ordered_list=[]
    for i in range(1,len(listed)+1):
    if dictionary[str(i)]:
        ordered_list.append(dictionary[str(i)])

for sub_list in ordered_list:
    print sub_list

【问题讨论】:

  • 把代码放到问题里面,没那么长!
  • @heltonbiker 当然,但我也会留下链接,因为它列出了错误和行号。
  • 如果您按原样使用,提供的大多数答案将在 n^2 * log(n) 时间内运行。您应该优化以确保您的浮动首先出现在子列表中,并采用使用第一个元素的快捷方式,以免每次都在列表中搜索它。
  • @Wug 是的,我确定在另一种算法中可以做到这一点。但这种效率是否与小系列数据相关?就目前而言,每个子列表可能不会超过 50 个值(很少这么高),并且子列表将少于 15 个。以前的算法效率课程让我相信,对于这样的少量数据,我只会节省几毫秒,即使 big-O 效率要好得多
  • 对于小型数据集,它可能无关紧要。对于可能包含一百个元素的一百个列表的任何内容,您可能会看到明显的差异。

标签: python list sorting dictionary


【解决方案1】:

您的错误是因为您的代码中没有“1”元素。它实际上是“1.0”(因为它是一个浮点数),这样做会使代码工作:

for i in range(1,len(listed)+1):
    if dictionary[str(float(i))]:
        ordered_list.append(dictionary[str(float(i))])

但是,在我看来,这远不是一个很好的方法来做你想做的事情,很多人都为替代方案提供了很好的建议。

【讨论】:

    【解决方案2】:
    >>> listed = [ ["1 NWZ", "1 RWZ", "2 NWZ", "2 RWZ", "1E HZ", "1W HZ", "1-2EHZ", 2.0, "2W HZ"],
    ["1 NWZ", "1W HZ", "3E FZ", "SNOK", "POK", 3.0, "1-2EHZ", "2E AK", "2W HZ"],
    ["1 BW", "1AW AS", "3E FZ", "1BWAK", "POK", "TESTK", "1-2EHZ", "2E AK", 1.0]]
    >>> listed
    [['1 NWZ', '1 RWZ', '2 NWZ', '2 RWZ', '1E HZ', '1W HZ', '1-2EHZ', 2.0, '2W HZ'], ['1 NWZ', '1W HZ', '3E FZ', 'SNOK', 'POK', 3.0, '1-2EHZ', '2E AK', '2W HZ'], ['1 BW', '1AW AS', '3E FZ', '1BWAK', 'POK', 'TESTK', '1-2EHZ', '2E AK', 1.0]]
    >>> dictionary ={}
    >>> for index,sub_list in enumerate(listed):
        for value in sub_list:
            if isinstance(value,float):
                dictionary[value]=index
            else:
                pass
    
    
    >>> dictionary
    {1.0: 2, 2.0: 0, 3.0: 1}
    >>> it = sorted(dictionary.items())
    >>> it
    [(1.0, 2), (2.0, 0), (3.0, 1)]
    >>> ordered_list = []
    >>> for item in it:
        ordered_list.append(listed[item[1]])
    
    
    >>> ordered_list
    [['1 BW', '1AW AS', '3E FZ', '1BWAK', 'POK', 'TESTK', '1-2EHZ', '2E AK', 1.0], ['1 NWZ', '1 RWZ', '2 NWZ', '2 RWZ', '1E HZ', '1W HZ', '1-2EHZ', 2.0, '2W HZ'], ['1 NWZ', '1W HZ', '3E FZ', 'SNOK', 'POK', 3.0, '1-2EHZ', '2E AK', '2W HZ']]
    >>> 
    

    【讨论】:

      【解决方案3】:

      sort method 有一个方便的 key 关键字参数,让您可以指定要调用的函数以确定列表应根据哪些信息进行排序。

      对列表进行排序就像编写一个返回每个子列表中包含的浮点值的函数一样简单:

      def sortOnFloat(sublist):
          return [v for v in sublist if isinstance(v, float)]
      

      请注意,我只是返回所有浮点值的list;比只退回一个要容易得多。即使子列表中有 0 个浮点值,这也会起作用。

      像这样对你的列表进行排序:

      listed.sort(key=sortOnFloat)
      

      我已经克隆了您的示例并使用上述方法对其进行了更新:http://ideone.com/u8ufK

      生成的输出:

      ['1 BW', '1AW AS', '3E FZ', '1BWAK', 'POK', 'TESTK', '1-2EHZ', '2E AK', 1.0]
      ['1 NWZ', '1 RWZ', '2 NWZ', '2 RWZ', '1E HZ', '1W HZ', '1-2EHZ', 2.0, '2W HZ']
      ['1 NWZ', '1W HZ', '3E FZ', 'SNOK', 'POK', 3.0, '1-2EHZ', '2E AK', '2W HZ']
      

      请注意,.sort() 方法对列表进行就地排序。您也可以使用sorted() function 生成一个已经排序的新列表;它采用相同的参数:

      orderedlist = sorted(listed, key=sortOnFloat)
      

      但请注意,就地排序总是更快。

      【讨论】:

      • 太棒了,我要测试一下,然后再回复你。还要感谢 sort 和 sorted 之间的简单区分,我从来不知道有区别!
      • 效果很好!非常感谢!这比在字典周围循环更简单
      【解决方案4】:

      也许这个链接可以帮助你,它提供了在几乎所有语言中实现自定义排序的方法。

      Sort using a custom comparator

      【讨论】:

      • 这是一个很棒的链接,我相信我将来会使用它。谢谢!
      【解决方案5】:

      创建一个函数来提取要排序的键,然后调用sorted

      listed = [ ["1 NWZ", "1 RWZ", "2 NWZ", "2 RWZ", "1E HZ", "1W HZ", "1-2EHZ", 2.0, "2W HZ"],
      ["1 NWZ", "1W HZ", "3E FZ", "SNOK", "POK", 3.0, "1-2EHZ", "2E AK", "2W HZ"],
      ["1 BW", "1AW AS", "3E FZ", "1BWAK", "POK", "TESTK", "1-2EHZ", "2E AK", 1.0]] 
      
      def get_key(l):
          return next(e for e in l if type(e) is float)
      
      print sorted(listed, key=get_key)
      

      【讨论】:

        【解决方案6】:

        您收到错误,因为列表中的数字是浮点数,但您使用整数查找键:

        listed = [ ["1 NWZ", "1 RWZ", "2 NWZ", "2 RWZ", "1E HZ", "1W HZ", "1-2EHZ", 2.0, "2W HZ"],
        ["1 NWZ", "1W HZ", "3E FZ", "SNOK", "POK", 3.0, "1-2EHZ", "2E AK", "2W HZ"],
        ["1 BW", "1AW AS", "3E FZ", "1BWAK", "POK", "TESTK", "1-2EHZ", "2E AK", 1.0]]
        
        dictionary={}
        for sub_list in listed:
            for value in sub_list:
                if isinstance(value,float):  #### you look for floats
                    dictionary[str(value)]=sub_list   ### the key is created as string
                else:
                    pass
        ordered_list=[]
        for i in range(1,len(listed)+1):   ### this is a range of INTS!!!!
            if dictionary[str(i)]:
                ordered_list.append(dictionary[str(i)])  #### str(i) is '1', not '1.0' 
        
        for sub_list in ordered_list:
            print sub_list
        

        我只能认为这不是好的代码。首先,不应该在同一个列表中混合字符串和数字。如果您创建该列表,我建议您使用字典,例如:

        listitem = {'number': 2.0, 'strings': ['1 NHZ', '1 RWZ', 'TESTK']}
        

        希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 2015-04-06
          • 2017-09-08
          • 2021-10-31
          • 2010-10-29
          • 1970-01-01
          • 2021-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多