用多个条件对元组列表进行排序

我有一个k元素的元组列表。我想对元素0进行排序,然后对元素1进行排序,依此类推。我用谷歌搜索,但我仍然不知道该怎么做。会是这样吗?

list.sort(key = lambda x : (x[0], x[1], ...., x[k-1])

特别是,我想使用不同的条件进行排序,例如,从元素0降序,从元素1升序,依此类推。

评论
  • 海绵宝宝
    海绵宝宝 回复

    Since python's sort is stable for versions after 2.2 (or perhaps 2.3), the easiest implementation I can think of is a serial repetition of sort using a series of index, reverse_value tuples:

    # Specify the index, and whether reverse should be True/False
    sort_spec = ((0, True), (1, False), (2, False), (3, True))
    
    # Sort repeatedly from last tuple to the first, to have final output be
    # sorted by first tuple, and ties sorted by second tuple etc
    for index, reverse_value in sort_spec[::-1]:
        list_of_tuples.sort(key = lambda x: x[index], reverse=reverse_value)
    

    这会进行多次,因此就恒定的时间成本而言可能效率低下,但就渐进复杂度而言仍为O(nlogn)。

    If the sort order for indices is truly 0, 1... n-1, n for a list of n-sized tuples as shown in your example, then all you need is a sequence of True and False to denote whether you want reverse or not, and you can use enumerate to add the index.

    sort_spec = (True, False, False, True)
    for index, reverse_value in list(enumerate(sort_spec))[::-1]:
        list_of_tuples.sort(key = lambda x: x[index], reverse=reverse_value)
    

    虽然原始代码允许按索引的任何顺序进行排序的灵活性。

    Incidentally, this "sequence of sorts" method is recommended in the Python Sorting HOWTO with minor modifications.

    编辑 如果您不需要按某些索引升序排序,而按其他索引降序排序,则

    from operator import itemgetter
    list_of_tuples.sort(key = itemgetter(1, 3, 5))
    

    将按索引1排序,然后按索引3排序关系,按索引5进一步排序关系。但是,更改每个索引的升序/降序并不容易。

  • pnon
    pnon 回复

    因此,我假设您要对tuple_0进行升序排序,然后对tuple_1进行降序排序,依此类推。有点冗长,但这是您可能正在寻找的:

    ctr = 0
    for i in range(list_of_tuples):
        if ctr%2 == 0:
            list_of_tuples[0] = sorted(list_of_tuples[0])
        else:
            list_of_tuples[0] = sorted(list_of_tuples[0], reverse=True)
        ctr+=1
    
    print list_of_tuples
    
  • 钱海秋
    钱海秋 回复
     list.sort(key = lambda x : (x[0], x[1], ...., x[k-1])
    

    This is actually using the tuple as its own sort key. In other words, the same thing as calling sort() with no argument.

    如果我假设您简化了问题,并且实际元素实际上并不是按照您想要的排序顺序排序(例如,最后一个值的优先级最高),则可以使用相同的技术,但是可以对排序基于优先级的密钥:

     list.sort(key = lambda x : (x[k-1], x[1], ...., x[0])
    

    通常,这是一个非常方便的技巧,即使在C ++之类的其他语言中(如果您使用的是库):当您要按优先级不同的多个成员对对象列表进行排序时,也可以通过创建一个按照优先级顺序包含所有相关成员的元组。

    Final trick (this one is off topic, but it may help you at some point): When using a library that doesn't support the idea of "sort by" keys, you can usually get the same effect by building a list that contains the sort-key. So, instead of sorting a list of Obj, you would construct then sort a list of tuples: (ObjSortKey, Obj). Also, just inserting the objects into a sorted set will work, if they sort key is unique. (The sort key would be the index, in that case.)