Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List sort based on another shorter list

I need to sort a list based on the order of the elements in another list which is shorter ie, doesn't have all the elements compared to the list I'm sorting. I run into this error when using the sort(key=short_list):

long_list = ['y', 'z', 'x', 'c', 'a', 'b']
short_list = ['b', 'c', 'a']
long_list.sort(key=short_list.index)

ValueError: 'x' is not in list

Is there another way to sort the long_list to result in a list that maintains the order of short_list followed by the order of the elements in the long_list?

['b', 'c', 'a', 'y', 'z', 'x']
like image 454
user2727704 Avatar asked Sep 27 '18 21:09

user2727704


People also ask

How do you sort a list according to another list?

Approach : Zip the two lists. Create a new, sorted list based on the zip using sorted(). Using a list comprehension extract the first elements of each pair from the sorted, zipped list.

How do you sort a list like another list in Python?

sort() is one of Python's list methods for sorting and changing a list. It sorts list elements in either ascending or descending order. sort() accepts two optional parameters. reverse is the first optional parameter.

Can you sort a nested list?

There will be three distinct ways to sort the nested lists. The first is to use Bubble Sort, the second is to use the sort() method, and the third is to use the sorted() method.


2 Answers

Something like this should work:

def position(value):
    try:
        return short_list.index(value)
    except ValueError:
        return len(short_list)

long_list.sort(key=position)

Sorting is guaranteed to be stable, so using len(short_list) ensures that the unknown values sort last.

like image 112
Florian Weimer Avatar answered Sep 30 '22 14:09

Florian Weimer


You can use in to detect if the element is in the short_list and a ternary to return a tuple based on that.:

>>> long_list = ['y', 'z', 'x', 'c', 'a', 'b']
>>> short_list = ['b', 'c', 'a']
>>> sorted(long_list, key=lambda e: (short_list.index(e),e) if e in short_list  else (len(short_list),e))
['b', 'c', 'a', 'x', 'y', 'z']

Since Python sorts are stable, the order will only change based on a change of the elements themselves. To make that change, we can use a tuple with either a (index_of_the_element, element) of (len(short_list), element) to effect that change.

If you want the elements to not change order if the element is not in short list, just return an empty tuple:

>>> sorted(long_list, key=lambda e: (short_list.index(e),e) if e in short_list  else (len(short_list),))
['b', 'c', 'a', 'y', 'z', 'x']
like image 27
dawg Avatar answered Sep 30 '22 14:09

dawg