列表的自定义排序顺序

6
我有一些列表,例如:
mylist1 = ['alpha', 'green']
mylist2 = ['blue', 'alpha', 'red']

我想按照这个自定义的顺序列表对这两个列表进行排序:['red','blue','green','alpha']

这样mylist1 = ['green', 'alpha']mylist2 = ['red','blue','alpha']

在Python中怎么做呢?

3个回答

14

演示:

>>> mylist1 = ['alpha', 'green']
>>> mylist2 = ['blue', 'alpha', 'red']
>>> sort_order = ['red', 'blue', 'green', 'alpha']
>>> mylist1.sort(key=sort_order.index)
>>> mylist1
['green', 'alpha']
>>> mylist2.sort(key=sort_order.index)
>>> mylist2
['red', 'blue', 'alpha']

说明:

list.sort函数中的key参数用于通过比较key(element)而不是element来确定列表的顺序。例如,要进行不区分大小写的排序,可以传递一个将字符串转换为小写的key函数。将比较小写元素,但原始元素得到保留:

>>> x = ["age", "Bonkers", "cheese"]
>>> x.sort()
>>> x
['Bonkers', 'age', 'cheese']
>>> str.lower("Bonkers")
'bonkers'    
>>> x.sort(key=str.lower)
>>> x
['age', 'Bonkers', 'cheese']

使用 sort_order.index 作为关键字按索引进行排序,而不是按元素本身。所以 'red' 使用的是 0'blue' 使用的是 1,依此类推... 结果是被排序的列表根据每个元素在 sort_order 中的位置进行排序。


这取决于你的后续问题有多不同。如果看起来太不同,可以先编辑你的问题,如果确实有问题,可能会有人告诉你。 - Steven Rumbalski
2
为了提高性能,可以使用以下代码将sort_order排序: sort_order = {v:i for i,v in enumerate(['red', 'blue', 'green', 'alpha'])} - Steven Rumbalski
@StevenRumbalski:确实如此,但是那一行更长,不太明显,然后你需要.sort(key=lambda el: sort_order[el])或者sort_order.__getitem__。无论哪种方式,它看起来都不太好看,所以我会选择这种方法,除非速度最终变得很重要。 - Claudiu
@Caudiu:key=sort_order.get - Steven Rumbalski
@StevenRumbalski:哦,不错。而且如果值不存在,它也不会出错。确实很有趣。我一直在使用Python 2.6,所以我真的必须切换到2.7来利用字典和集合推导式。 - Claudiu
显示剩余5条评论

5

使用索引作为键。

key=lambda x: customlist.index(x)

2

您可以使用以下方法:

>>> a = ['red','blue','green','alpha']
>>> b = ['alpha', 'green']
>>> filter(set(b).__contains__, a)
['green', 'alpha']

我们不需要将列表排序,只需从已排序的列表a中包含在源列表b中的元素。

可以写成[el for el in a if el in b],如果需要,b可以作为一个set。

当然,如果你真的想要进行排序,那么你应该建立一个索引查找,而不是可能多次迭代列表(通过不断发出.index):

order = {v:i for i,v in enumerate(a)}
b.sort(key=order.get)

1
不是很符合 Python 的风格。你能否添加一些解释说明正在发生什么? - Brigand
@Dirk 不确定我理解你的意思?它有所需的输出...只是没有对列表进行物理排序,因为输出不需要进行排序操作才能成为指定的输出。 - Jon Clements

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