如何在Python中对单个元素中具有不同字符优先级的嵌套列表进行排序?

如何在Python中对单个元素中具有不同字符优先级的嵌套列表进行排序?,python,list,sorting,nested-lists,Python,List,Sorting,Nested Lists,很抱歉没能写出一个好标题 我有一份清单: some_list = [[X, '4x01'], [X, '3x02'], [X, '4x02'], [X, '3x01']] 其中X是我不在乎的东西 我想按照以下优先级对列表中的第二个元素进行排序: 按降序排列的第一个字符 最后2个字符按升序排列 最终输出应为: some_list = [[X, '4x01'], [X, '4x02'], [X, '3x01'], [X, '3x02']] 注意:给出错误答案的解决方案是: output = so

很抱歉没能写出一个好标题

我有一份清单:

some_list = [[X, '4x01'], [X, '3x02'], [X, '4x02'], [X, '3x01']]
其中
X
是我不在乎的东西

我想按照以下优先级对列表中的第二个元素进行排序:

  • 按降序排列的第一个字符
  • 最后2个字符按升序排列
  • 最终输出应为:

    some_list = [[X, '4x01'], [X, '4x02'], [X, '3x01'], [X, '3x02']]
    
    注意:给出错误答案的解决方案是:

    output = sorted(some_list, key=lambda lis: lis[3], reverse=True)
    
    示例运行(将X定义为
    None
    以便我可以复制粘贴列表定义):


    在这种情况下,您可以像@Amber那样使用复合键。然而,这种方法并不总是有效的:例如,如果两个组件都有两个字符长,它就会失败(因为
    -ord(x[1][0])
    技巧不再有效)

    以下是一个更通用的解决方案:

    In [15]: X = None
    
    In [16]: some_list = [[X, '4x01'], [X, '3x02'], [X, '4x02'], [X, '3x01']]
    
    In [17]: l = sorted(some_list, key=lambda (x,y):y[-2:])
    
    In [18]: l = sorted(l, key=lambda (x,y):y[:1], reverse=True)
    
    In [19]: l
    Out[19]: [[None, '4x01'], [None, '4x02'], [None, '3x01'], [None, '3x02']]
    
    它一次按一个标准对列表进行排序,并利用Python的排序是不正确的这一事实

    更一般的方法是提供一个比较标准:

    def f((x1,y1), (x2,y2)):
        c = cmp(y1[:1], y2[:1])
        if c != 0: return -c
        return cmp(y1[-2:], y2[-2:])
    
    这可以按如下方式使用:

    In [39]: sorted(some_list, cmp=f)
    Out[39]: [[None, '4x01'], [None, '4x02'], [None, '3x01'], [None, '3x02']]
    

    这是正确的。尽管思考了几个小时,我永远也不会得出这个答案。谢谢Spython一行非常好。您可以做很多事情,但仍然可以-与Perl相比,它们仍然是可读的。如果您做到这一点,更好的选择可能是只编写一个比较函数。这将避免您必须对列表进行两次排序(如果列表很大,这可能是一项昂贵的操作)。@Amber:Fair point。不过,这是一个值得了解的有用技巧。请帮助我理解你的论点。如果是两个字符长的话,
    -ord(x[1][:1])
    会不会改成这样呢?@elwc:我想你的意思是
    -ord(x[1][:2])
    。这将引发异常,因为
    ord()
    只能应用于单个字符串。
    -ord(…)
    技巧依赖于
    ..
    正好是一个字符长。你的假设很好。难怪我没有出错。关于刚才提到的比较函数@Amber,那是什么?
    def f((x1,y1), (x2,y2)):
        c = cmp(y1[:1], y2[:1])
        if c != 0: return -c
        return cmp(y1[-2:], y2[-2:])
    
    In [39]: sorted(some_list, cmp=f)
    Out[39]: [[None, '4x01'], [None, '4x02'], [None, '3x01'], [None, '3x02']]