Sort a list of lists with a custom compare function

后端 未结 4 2026
一向
一向 2020-12-07 15:22

I know there are several questions named like this, but they don\'t seem to work for me.

I have a list of lists, 50 times 5 elements. I want to sort this list by app

相关标签:
4条回答
  • 2020-12-07 16:07
    >>> l = [list(range(i, i+4)) for i in range(10,1,-1)]
    >>> l
    [[10, 11, 12, 13], [9, 10, 11, 12], [8, 9, 10, 11], [7, 8, 9, 10], [6, 7, 8, 9], [5, 6, 7, 8], [4, 5, 6, 7], [3, 4, 5, 6], [2, 3, 4, 5]]
    >>> sorted(l, key=sum)
    [[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 10], [8, 9, 10, 11], [9, 10, 11, 12], [10, 11, 12, 13]]
    

    The above works. Are you doing something different?

    Notice that your key function is just sum; there's no need to write it explicitly.

    0 讨论(0)
  • 2020-12-07 16:12

    Also, your compare function is incorrect. It needs to return -1, 0, or 1, not a boolean as you have it. The correct compare function would be:

    def compare(item1, item2):
        if fitness(item1) < fitness(item2):
            return -1
        elif fitness(item1) > fitness(item2):
            return 1
        else:
            return 0
    
    # Calling
    list.sort(key=compare)
    
    0 讨论(0)
  • 2020-12-07 16:16

    Since the OP was asking for using a custom compare function (and this is what led me to this question as well), I want to give a solid answer here:

    Generally, you want to use the built-in sorted() function which takes a custom comparator as its parameter. We need to pay attention to the fact that in Python 3 the parameter name and semantics have changed.

    How the custom comparator works

    When providing a custom comparator, it should generally return an integer/float value that follows the following pattern (as with most other programming languages and frameworks):

    • return a negative value (< 0) when the left item should be sorted before the right item
    • return a positive value (> 0) when the left item should be sorted after the right item
    • return 0 when both the left and the right item have the same weight and should be ordered "equally" without precedence

    In the particular case of the OP's question, the following custom compare function can be used:

    def compare(item1, item2):
        return fitness(item1) - fitness(item2)
    

    Using the minus operation is a nifty trick because it yields to positive values when the weight of left item1 is bigger than the weight of the right item2. Hence item1 will be sorted after item2.

    If you want to reverse the sort order, simply reverse the subtraction: return fitness(item2) - fitness(item1)

    Calling sorted() in Python 2

    sorted(mylist, cmp=compare)
    

    or:

    sorted(mylist, cmp=lambda item1, item2: fitness(item1) - fitness(item2))
    

    Calling sorted() in Python 3

    from functools import cmp_to_key
    sorted(mylist, key=cmp_to_key(compare))
    

    or:

    from functools import cmp_to_key
    sorted(mylist, key=cmp_to_key(lambda item1, item2: fitness(item1) - fitness(item2)))
    
    0 讨论(0)
  • 2020-12-07 16:20

    You need to slightly modify your compare function and use functools.cmp_to_key to pass it to sorted. Example code:

    import functools
    
    lst = [list(range(i, i+5)) for i in range(5, 1, -1)]
    
    def fitness(item):
        return item[0]+item[1]+item[2]+item[3]+item[4]
    def compare(item1, item2):
        return fitness(item1) - fitness(item2)
    
    sorted(lst, key=functools.cmp_to_key(compare))
    

    Output:

    [[2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8], [5, 6, 7, 8, 9]]
    

    Works :)

    0 讨论(0)
提交回复
热议问题