From f0033f87e0b4082e55dd3641282e65369e03c03e Mon Sep 17 00:00:00 2001 From: Mozartus <32893711+Mozartuss@users.noreply.github.com> Date: Thu, 15 Oct 2020 13:45:17 +0200 Subject: [PATCH] Create natural_sort.py (#3286) * add natural_sort.py * fix doctest * add 're' to requirements.txt and fix spelling errors * delete 're' from requirements.txt * fixing linting errors * Update sorts/natural_sort.py Co-authored-by: Christian Clauss * Update sorts/natural_sort.py Co-authored-by: Christian Clauss * Update natural_sort.py Co-authored-by: Christian Clauss --- sorts/natural_sort.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 sorts/natural_sort.py diff --git a/sorts/natural_sort.py b/sorts/natural_sort.py new file mode 100644 index 000000000..001ff2cf5 --- /dev/null +++ b/sorts/natural_sort.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import re + + +def natural_sort(input_list: list[str]) -> list[str]: + """ + Sort the given list of strings in the way that humans expect. + + The normal Python sort algorithm sorts lexicographically, + so you might not get the results that you expect... + + >>> example1 = ['2 ft 7 in', '1 ft 5 in', '10 ft 2 in', '2 ft 11 in', '7 ft 6 in'] + >>> sorted(example1) + ['1 ft 5 in', '10 ft 2 in', '2 ft 11 in', '2 ft 7 in', '7 ft 6 in'] + >>> # The natural sort algorithm sort based on meaning and not computer code point. + >>> natural_sort(example1) + ['1 ft 5 in', '2 ft 7 in', '2 ft 11 in', '7 ft 6 in', '10 ft 2 in'] + + >>> example2 = ['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9'] + >>> sorted(example2) + ['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9'] + >>> natural_sort(example2) + ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13'] + """ + + def alphanum_key(key): + return [int(s) if s.isdigit() else s.lower() for s in re.split("([0-9]+)", key)] + + return sorted(input_list, key=alphanum_key) + + +if __name__ == "__main__": + import doctest + + doctest.testmod()