Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python sort list based on key sorted list

I have a predefined list which indicates the order of some values:

['id','name','age','height','weight',]

(can be very long)

I want to sort any subset of this list:

So if i get ['height','id'] It will become ['id','height']

or ['name','weight','height'] ---> ['name','height','weight']

Is there some way to do it with the sort function using the key paramter somehow? or should I use a custom method, if so what will be most efficient?

like image 432
YardenST Avatar asked Aug 02 '13 12:08

YardenST


People also ask

Can you sort by key dictionary Python?

Need for Sorting in Dictionary First, sort the keys alphabetically using key_value. iterkeys() function. Second, sort the keys alphabetically using the sorted (key_value) function & print the value corresponding to it. Third, sort the values alphabetically using key_value.

How do you sort a key function in Python?

Custom Sorting With key= For example with a list of strings, specifying key=len (the built in len() function) sorts the strings by length, from shortest to longest. The sort calls len() for each string to get the list of proxy length values, and then sorts with those proxy values.


2 Answers

The most efficient way would be to create a map from word to order:

ordering = {word: i for i, word in enumerate(predefined_list)}

then use that mapping in sorting:

somelist.sort(key=ordering.get)

The alternative is to use .index() on the list to scan through the list and find the index for each word while sorting:

somelist.sort(key=predefined_list.index)

but this is not nearly as efficient as using the ordering dictionary.

Demo:

>>> predefined_list = ['id','name','age','height','weight',]
>>> ordering = {word: i for i, word in enumerate(predefined_list)}
>>> sorted(['height','id'], key=ordering.get)
['id', 'height']
>>> sorted(['name','weight','height'], key=ordering.get)
['name', 'height', 'weight']

The two methods would result in different sorting orders if any of the values in the predefined list were not unique. The .index() method uses the first occurrence of a value as the sort value, the dictionary method would use the last instead. There are ways around that, you can make the dictionary method process the list and indices in reverse for example.

like image 83
Martijn Pieters Avatar answered Oct 15 '22 23:10

Martijn Pieters


The shortest solution:

lst  = ['id', 'name', 'age', 'height', 'weight',]
test = ['name', 'weight', 'height']

print [word for word in lst if word in test]

Returns:

['name', 'height', 'weight']

This shows all items from lst in that order only if the item is contained in test. Advantage: no sorting needed.

After comments:

Disadvantages: - Duplicates might not be shown - The 'in' operator is meaning a traversal; same as the second one. So if the list is long it might be inefficient. However the solution from Martijn also has two sorts so I cannot decide easily which is more efficient.

like image 37
Michel Keijzers Avatar answered Oct 15 '22 23:10

Michel Keijzers