1

希望这会有意义...

我有以下形式的元组列表:

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]

所需的输出是

sorted_list_of_tuples = [('a', 1), ('b', 2), ('b', 3), ('a', 3)]

问题是我希望第二个条目增加,而第一个条目减少。

import operator as op     
sorted_list_of_tuples = sorted(list_of_tuples, key=op.itemgetter(2, 0))

当然,这会将两个字段排序为增加。我想不出一个可爱的(即几行)方法来做到这一点。有没有人有办法轻松完成这种排序?

我似乎记得您可以使用 引用括号内的列表理解的元素_,所以也许这是一个开始的地方?


也许我不清楚:这种情况下的整数更重要。它的顺序应该在整个列表中增加。当有平局时(即..,第二个条目相等),我希望 'b' 出现在 'a' 之前。

4

2 回答 2

3

如果您可以用英语描述键,只需将其翻译为函数即可。

我希望第二个条目增加,第一个条目减少。

所以,关键是:

def make_key(my_tuple):
    return my_tuple[1], -my_tuple[0]

当然,除非-这在弦乐上不起作用,所以你需要更花哨的东西。

或者,也许不是……虽然每个元组的第一个元素是一个字符串,第二个元素是一个整数,所以,我们可以对 key 函数取反,并使用reverse它来取消它:

def make_key(my_tuple):
    return -my_tuple[1], my_tuple[0]

sorted_list_of_tuples = sorted(list_of_tuples, key=make_key, reverse=True)

如果您想节省一些击键:

sorted_list_of_tuples = sorted(list_of_tuples,
                               key=lambda x: (x[1], x[0]), reverse=True)

这不是唯一可行的技巧。例如,因为您的所有字符串都是 1 个字符的字符串,所以ord(x) < ord(y)iff x < y

但有时你想不出一个简单的技巧——但你可以想出一个简单的方法来编写一个比较函数。如果它更具可读性,请这样做:

def compare_my_tuples(lhs, rhs):        
    if rhs[1] > lhs[0]: return 1
    elif rhs[1] < lhs[0]: return -1
    elif rhs[0] > lhs[0]: return -1
    elif rhs[0] < rhs[0]: return 1
    else: return 0

sorted_list_of_tuples = sorted(list_of_tuples, 
                               key=functools.cmp_to_key(compare_my_tuples))

或者,当然,您可以将其分为两种,如 steveha 的回答。(是的,它可能需要两倍的时间……但在大多数应用程序中,这根本不会产生任何影响。)

于 2013-05-02T22:27:13.030 回答
2

当然。Python 的内置排序是一种“稳定”排序。所以,选择你想要更重要的那一种,然后一秒钟就完成。做不太重要的排序,然后再按更重要的标准排序。

工作代码:

import operator as op

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]

list_of_tuples.sort(key=op.itemgetter(0), reverse=True)
list_of_tuples.sort(key=op.itemgetter(1))

assert list_of_tuples == [('a', 1), ('b', 2), ('b', 3), ('a', 3)]

我想如果你想出一个聪明的关键功能,你可以一次完成整个事情。也许是这样:

def custom_key_fn(tup):
    ch, n = tup # unpack tuple
    return (n, -ord(ch))

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]
list_of_tuples.sort(key=custom_key_fn)

assert list_of_tuples == [('a', 1), ('b', 2), ('b', 3), ('a', 3)]
于 2013-05-02T22:26:00.373 回答