Custom Python list sorting
It's documented here.
The sort() method takes optional arguments for controlling the
comparisons.cmp specifies a custom comparison function of two arguments (list
items) which should return a negative, zero or positive number
depending on whether the first argument is considered smaller than,
equal to, or larger than the second argument: cmp=lambda x,y:
cmp(x.lower(), y.lower()). The default value is None.
Custom sort order in Python
There's no need to use a lambda in the sorted function. Just supply it the index
function of list1
:
sorted(list2, key=list1.index)
Sort a list of lists with a custom compare function
>>> 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.
How to custom sort a list in python
First of all, make your keyorder
a dict because list.index
is an O(n)
operation you don't want to perform for every comparison the sorting algorithm does.
>>> keyorder = 'ID', 'GE','FN','LN','MN','EM', 'ST'
>>> keyorder = dict(zip(keyorder, range(len(keyorder))))
>>>
>>> keyorder
{'FN': 2, 'GE': 1, 'ID': 0, 'LN': 3, 'ST': 6, 'EM': 5, 'MN': 4}
Now you can sort by splitting the part before the :
from each of your strings and get the corresponding priority from keyorder
.
>>> data = ['ID:123 GE:m FN:Amir LN:Maleki EM:a@b.c MN:0400101010 ST:VIC']
>>> data = data[0].split()
>>> sorted(data, key=lambda x: keyorder[x.split(':', 1)[0]])
['ID:123', 'GE:m', 'FN:Amir', 'LN:Maleki', 'MN:0400101010', 'EM:a@b.c', 'ST:VIC']
(The first two lines here sanitize your Data
list because it's just a list of one element containing a string.)
Python: How to custom order a list?
You could use a dictionary that would map every first element to its "weight" and then check this dictionary inside a sorting function.
Something like:
d = { "Report": 1,
"Article": 2,
"Book": 3 }
result = sorted(mylist, key=lambda x:d[x[0]])
How to custom sort in a Python list?
Your code fails with an AttributeError
because you are trying to do a lookup of id
in a dict
object, which doesn't have one. You need to access the desired dictionary key:
sorted(demo, key=lambda x: x['id'])
However, that will fail with a KeyError
if at least one entry in the list does not have the id
key. In that case, you can use:
sorted(demo, key=lambda x: x.get("id"))
Optionally you can use a default value in the get
, if you wish to put all the entries with no id
above or below the rest. In this case, the following would send entries with no id
to the bottom:
sorted(demo, key=lambda x: x.get("id", "99"))
It may also happen that you have an id
like 12#10
and you don't want it to be between 12#1
and 12#2
. To solve that problem, you need to split the id
and have a more complex sorting function.
def get_values(item):
return [int(x) for x in item['id'].split('#')]
def compare(a, b):
a = get_values(a)
b = get_values(b)
if not a[0] == b[0]:
return a[0] - b[0]
return a[1] - b[1]
Then you call sorted
using that comparison function:
sorted(demo, cmp=compare)
Or in Python 3, where cmp
has been eliminated:
from functools import cmp_to_key
sorted(demo, key=cmp_to_key(compare))
Custom sort order of list
Demonstration:
>>> mylist1 = ['alpha', 'green']
>>> mylist2 = ['blue', 'alpha', 'red']
>>> sort_order = ['red', 'blue', 'green', 'alpha']
>>> mylist1.sort(key=sort_order.index)
>>> mylist1
['green', 'alpha']
>>> mylist2.sort(key=sort_order.index)
>>> mylist2
['red', 'blue', 'alpha']
Explanation:
The key
parameter in list.sort
causes the list to determine the order by comparing key(element)
instead of element
. For example, to do case-insensitive sort, you can pass a key
function which makes the string lowercase. The lowercase elements are compared, but the original elements are preserved:
>>> x = ["age", "Bonkers", "cheese"]
>>> x.sort()
>>> x
['Bonkers', 'age', 'cheese']
>>> str.lower("Bonkers")
'bonkers'
>>> x.sort(key=str.lower)
>>> x
['age', 'Bonkers', 'cheese']
Using sort_order.index
for the key uses the index that element has in the sort_order
list to determine the order instead of the element itself. So 'red'
uses 0
, 'blue'
uses 1
, etc... the result is that the list to be sorted gets sorted according to where each element is in sort_order
.
Sort a list with a custom order in Python
SORT_ORDER = {"DINT": 0, "INT": 1, "BOOL": 2}
mylist.sort(key=lambda val: SORT_ORDER[val[1]])
All we are doing here is providing a new element to sort on by returning an integer for each element in the list rather than the whole list. We could use inline ternary expressions, but that would get a bit unwieldy.
Sorting list with custom order in Python
You must sort according to the first letter of the words:
list1 = ['Alpha', 'Beta', 'Charlie', 'Delta', 'Echo']
list2 = ['B', 'A', 'E', 'C', 'D']
out = list(sorted(list1, key=lambda word: list2.index(word[0])))
print(out)
# ['Beta', 'Alpha', 'Echo', 'Charlie', 'Delta']
index
will have to iterate on list2
each time though. It might be more efficient to build a dict giving the index of each letter first, so that we can find the indices in O(1) when sorting:
list1 = ['Alpha', 'Beta', 'Charlie', 'Delta', 'Echo']
list2 = ['B', 'A', 'E', 'C', 'D']
dict2 = {letter: index for index, letter in enumerate(list2)}
out = list(sorted(list1, key=lambda word: dict2[word[0]]))
print(out)
# ['Beta', 'Alpha', 'Echo', 'Charlie', 'Delta']
Related Topics
Splitting a Pandas Dataframe Column by Delimiter
Index of Duplicates Items in a Python List
Filling in Login Forms in Instagram Using Selenium and Webdriver (Chrome) Python Osx
Why Doesn't a Python Dict.Update() Return the Object
Repeat Rows in a Pandas Dataframe Based on Column Value
Which Is the Easiest Way to Simulate Keyboard and Mouse on Python
Sorting a List of Dot-Separated Numbers, Like Software Versions
How to Avoid Explicit 'Self' in Python
What's the Difference Between %S and %D in Python String Formatting
Split a Python List into Other "Sublists" I.E Smaller Lists
Two Variables in Python Have Same Id, But Not Lists or Tuples
Why Does Sys.Exit() Not Exit When Called Inside a Thread in Python