Search code examples
pythonlistsortingnested-lists

Sort by order of another list, where that list is nested with 2 sort keys, using Python


I know how to sort one list to match the order of another list. I also know how to sort one list on two keys (using a lamdba function like key = lambda i: (i[0], i[1])). But I need to sort one list to match the order of another list, where that second list has two sort keys. For example:

order_list = [['a', 2], ['c', 3], ['b', 1], ['e', 4]]
listB = [['c', 3, 'red', 'car'], ['e', 4, 'green', 'bus'], ['b', 1, 'blue', 'bike'], ['a', 2, 'yellow', 'plane']]

Desired output:

sorted_listB = [['a', 2, 'yellow', 'plane'], ['c', 3, 'red', 'car'], ['b', 1, 'blue', 'bike'],['e', 4, 'green', 'bus']]

I tried by writing this - even though it's bad form I just wanted to see if it would work and it does not:

def sort_key(x):
    """ Find the matching element in reference sorted list
    """
    # bad form, referencing non-local var
    for a in order_list:
        if a[0] == x[0] and a[1] == x[1]:
            return a

    sorted_listB = sorted(listB, key = sort_key)

Any clever thoughts on how to do this? Preferably without turning the nested list into a single key. I know I can do that...was trying to stretch my skills and do it this way, but I'm stuck.


Solution

  • One approach:

    order_list = [['a', 2], ['c', 3], ['b', 1], ['e', 4]]
    listB = [['c', 3, 'red', 'car'], ['e', 4, 'green', 'bus'], ['b', 1, 'blue', 'bike'], ['a', 2, 'yellow', 'plane']]
    
    # use a dictionary to map the values to the priorities
    keys = {tuple(e): i for i, e in enumerate(order_list)}
    
    # then use the first to elements of each sub-list to check for the priority
    sorted_listB = sorted(listB, key=lambda x: keys.get(tuple(x[:2])))
    print(sorted_listB)
    print(sorted_listB)
    

    Output

    [['a', 2, 'yellow', 'plane'], ['c', 3, 'red', 'car'], ['b', 1, 'blue', 'bike'], ['e', 4, 'green', 'bus']]
    

    Or, if you wish, fix your function to return index values using enumerate as below:

    def sort_key(x):
        """ Find the matching element in reference sorted list
        """
        # bad form, referencing non-local var
        for i, a in enumerate(order_list):
            if a[0] == x[0] and a[1] == x[1]:
                return i