Python:按字母顺序(不区分大小写)对元组列表进行排序

3

我有一组元组(“twoples”)的列表

[('aaa',2), ('BBB',7), ('ccc',0)]

我需要按照那个顺序打印它,但是

>>> sorted([('aaa',2), ('BBB',7), ('ccc',0)])

提供

[('BBB', 7), ('aaa', 2), ('ccc', 0)]

list.sort(key=str.tolower)

这不起作用(显然),因为

AttributeError: type object 'str' has no attribute 'tolower'

我不想改变列表中的字符串。

另一个答案给出了:

list.sort(key=lambda (a, b): (a.lower(), b))

不过那一定是Python 2的事情了,因为

SyntaxError: invalid syntax

首先(

itemgetter() 没有帮助,因为只允许一个“key”

2个回答

8

您说得对,这是Python 2的问题,但修复方法很简单:

list.sort(key=lambda a: (a[0].lower(), a[1]))

这似乎并不更加清晰,因为名称ab并没有比a[0]a[1]更多的内在含义。(如果它们是像namescore这样的,则可能会有所不同...)。
Python 2允许将函数参数解包为元组。这在一些简单的情况下可行(有时也很方便),但存在很多问题。请参阅PEP 3113以了解其被移除的原因。
处理此问题的规范方法是在函数内部仅拆分值,这在lambda中并不完全适用。但是是否有理由不能在函数外部定义函数呢?
def twoplekey(ab):
    a, b = ab
    return a.lower(), b

list.sort(key=twoplekey)

作为一个旁注,您真的不应该将您的列表命名为list; 这会隐藏 list 类型,因此您将无法再使用它(例如,如果您想通过编写 list(tup)将元组转换为列表,则将尝试调用您的列表,并获得令人困惑的错误)。

我几乎用我的第一个lambda表达式就做到了 - 我没有想到要把a和b都放进去。你的两个解决方案都完美地工作了(现在我可以将它们扩展到更复杂的情况)。 我认为你最后一个问题的答案是:函数(如lambda表达式)应用于列表的每一行。 (我只称它为“列表”,以显示我正在使用一个列表。) - ZZMike
PS:我刚刚尝试了使用字典(使用“D=dict(mylist)”),毫不意外,它同样有效。 - ZZMike
@ZZMike:是的,我的观点是,使用def定义的函数,就像使用lambda内联定义的函数一样,可以很容易地应用于列表的每一行。因此,如果您无法使用lambda编写某些内容,您始终可以使用def(它允许您包括赋值和其他语句)。 - abarnert

0
以下代码适用于Python 3:
>>> my_list = [('aaa',2), ('BBB',7), ('ccc',0)]
>>> my_list.sort(key=lambda elem: elem[0].lower())
>>> print(my_list)
[('aaa', 2), ('BBB', 7), ('ccc', 0)]

函数参数解包在Python 3中不起作用(正如您所发现的那样),但从问题的措辞来看,似乎您只关心每个元组的第一个元素(elem [0])的比较。此示例集中于此并忽略第二个元素(elem [1])。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接