希望这有意义......
我有以下格式的元组列表:
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'之前。
答案 0 :(得分:3)
如果您能用英语描述密钥,只需将其翻译成函数即可。
我希望第二个条目增加,第一个条目减少。
所以,关键是:
def make_key(my_tuple):
return my_tuple[1], -my_tuple[0]
当然,除了-
在字符串上不起作用之外,所以你需要更高级的东西。
或者,也许不是......虽然每个元组的第一个元素是一个字符串,但第二个元素是一个整数,因此,我们可以忽略键函数,并使用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))
或者,当然,你可以把它分成两种,就像史蒂夫的回答一样。 (是的,它可能需要两倍的时间......但在大多数应用程序中,这根本不会产生任何差异。)
答案 1 :(得分: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)]