在Python中按自定义顺序对列表进行排序

39

我有一个列表

mylist = [['123', 'BOOL', '234'], ['345', 'INT', '456'], ['567', 'DINT', '678']]

我想按照以下顺序排序:1. DINT 2. INT 3. BOOL

结果:

[['567', 'DINT', '678'], ['345', 'INT', '456'], ['123', 'BOOL', '234']]

我在stackoverflow上看到了其他类似的问题,但没有类似或易于应用于我。


您有一个语法错误:'345未关闭。 - K.-Michael Aye
我想按照以下顺序排序:1. DINT 2. INT 3. BOOL。那是什么顺序?如果我添加另一项 ['317.3','FLOAT','268.0'],我如何知道它在排序后的输出中应该放在哪里? - Karl Knechtel
@KarlKnechtel 嗯,这个的完整应用是对REAL(浮点数)、DINT、INT、SINT和BOOL进行排序。这是我想要的顺序(从大到小)。这里的问题只是为了举例说明。 '123','234','345'...都没有实际意义。 - elwc
5个回答

80
SORT_ORDER = {"DINT": 0, "INT": 1, "BOOL": 2}

mylist.sort(key=lambda val: SORT_ORDER[val[1]])

我们在这里所做的一切就是提供一个新元素,通过为列表中的每个元素返回一个整数而不是整个列表进行排序。 我们可以使用内联三元表达式,但这会变得有些笨重。


@SeanVieira,如果我们有一个排序顺序,但有时候我们想要排序的列表中并不包含所有的键,你会如何扩展它? - joddm
4
Python中的字典对象有一个.get方法,可以用来获取键对应的值,因此你可以使用如下代码:lambda val: SORT_ORDER.get(val[1], "我的默认排序方式")。@joddm - Sean Vieira
3
不错,但是以此为灵感,我更喜欢 SORT_ORDER = ["DINT", "INT", "BOOL"] mylist.sort(key=lambda val: SORT_ORDER.index(val))。我想也许这样做的速度没有使用索引快?但它似乎更容易解释。 - James

2
另一种方法是将您的订单列在列表中:
indx = [2,1,0]

并创建一个包含您所需订单的新列表:

mylist = [mylist[_ind] for _ind in indx]

Out[2]: [['567', 'DINT', '678'], ['345', 'INT', '456'], ['123', 'BOOL', '234']]

0

由于它不是按字母顺序排列的,我认为没有一个单一的函数可以对其进行排序,但您可以创建一个新列表,然后进行附加。这是一种比较简单的方法,但它能够完成工作。

newlist=[];
for sub_list in mylist:
     if(sub_list[1] == 'DINT']):
          newlist.append(sub_list);

for sub_list in mylist:
     if(sub_list[1] == 'INT']):
         newlist.append(sub_list);

for sub_list in mylist:
     if(sub_list[1] == 'BOOL']):
            newlist.append(sub_list);

1
即使这种方法有道理,为了所有神圣的爱,请使用列表推导式、filter或其他方法。 - Karl Knechtel
1
@KarlKnechtel:我不知道你怎么能说这种方法没有意义……我测试过它,而且它有效。但是有一件事叫做建设性批评;没有必要对陌生人无礼。 - Devon Bernard
4
在设置循环时,我总是尝试想一想如何减少数据通过的次数。在这种情况下,您需要循环三次才能找到三个不同的变量,所以挑战在于找到一种方法,在单次遍历中获取所有信息(因为您将在单次遍历中遇到所有变量)。肖恩的解决方案使用字典来实现这一点,因此每次遇到一个项目时,您都知道它应该放在哪里。此外,您应该一定要看一下列表理解 - 您很快就会爱上它们的 :) - RocketDonkey
@RocketDonkey:谢谢,这很有道理。我最初也想到了类似的方法;只是我不确定如果elwc有多个相同变量的项目,例如:5个“INT”,3个“DINT”和4个“BOOL”,那么这种方法是否有效。所以我认为尝试那种方式更安全,即使我说过那是便宜的方法。 :) - Devon Bernard
哈,是的,它能正常工作,所以你不能太苛刻了 :) 由于Python排序是稳定的,在多个出现的情况下,它们将按照传递到排序函数中的顺序返回(所以你走在了正确的轨道上)。 - RocketDonkey
显示剩余2条评论

0
你可以通过列表来定义一个明确的顺序。
def explicit_order(xs):
    """Return a key function that, when passed to sort or sorted, will sort
    the elements in the order they appear in this list.
    """
    keys = {x: i for i, x in enumerate(xs)}
    def key_function(x):
        return keys[x]
    return key_function

order = explicit_order(['DINT', 'INT', 'BOOL'])
sorted(['BOOL', 'INT'], key=order) # = ['INT', 'BOOL']

在你的例子中,由于你还需要从元组中提取字符串,所以你的键函数会稍微复杂一些。
sorted(mylist, key=lambda x: order(x[1]))

-1
     python 3.2

    1. sorted(mylist,key=lambda x:x[1][1])

    2. sorted(mylist,reverse=True)

第一种选择可行,但是假设标签名称不会改变。第二个选项不符合OP的要求。 - astraujums

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