summaryrefslogtreecommitdiff
path: root/cmd2/utils.py
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2018-09-19 18:11:33 -0400
committerGitHub <noreply@github.com>2018-09-19 18:11:33 -0400
commit25e388cc78002f78e93b946367b883a4802cfd4e (patch)
treec8d1f99b0726605a77edd13cb9055ce670f52e56 /cmd2/utils.py
parentb1a6dd3bdb27590aec4612ba4bd58eb416a60d07 (diff)
parentacd5c1ba5f4a74c0212e67eae3ac0f45d74cd9bc (diff)
downloadcmd2-git-25e388cc78002f78e93b946367b883a4802cfd4e.tar.gz
Merge pull request #524 from lancestarr/master
Add natural sorting (sorting case insensitively as well as numerically)
Diffstat (limited to 'cmd2/utils.py')
-rw-r--r--cmd2/utils.py48
1 files changed, 47 insertions, 1 deletions
diff --git a/cmd2/utils.py b/cmd2/utils.py
index 02956f6b..64401895 100644
--- a/cmd2/utils.py
+++ b/cmd2/utils.py
@@ -4,8 +4,9 @@
import collections
import os
-from typing import Any, List, Optional, Union
+import re
import unicodedata
+from typing import Any, List, Optional, Union
from . import constants
@@ -172,7 +173,52 @@ def norm_fold(astr: str) -> str:
def alphabetical_sort(list_to_sort: List[str]) -> List[str]:
"""Sorts a list of strings alphabetically.
+ For example: ['a1', 'A11', 'A2', 'a22', 'a3']
+
+ To sort a list in place, don't call this method, which makes a copy. Instead, do this:
+
+ my_list.sort(key=norm_fold)
+
:param list_to_sort: the list being sorted
:return: the sorted list
"""
return sorted(list_to_sort, key=norm_fold)
+
+
+def try_int_or_force_to_lower_case(input_str: str) -> Union[int, str]:
+ """
+ Tries to convert the passed-in string to an integer. If that fails, it converts it to lower case using norm_fold.
+ :param input_str: string to convert
+ :return: the string as an integer or a lower case version of the string
+ """
+ try:
+ return int(input_str)
+ except ValueError:
+ return norm_fold(input_str)
+
+
+def natural_keys(input_str: str) -> List[Union[int, str]]:
+ """
+ Converts a string into a list of integers and strings to support natural sorting (see natural_sort).
+
+ For example: natural_keys('abc123def') -> ['abc', '123', 'def']
+ :param input_str: string to convert
+ :return: list of strings and integers
+ """
+ return [try_int_or_force_to_lower_case(substr) for substr in re.split('(\d+)', input_str)]
+
+
+def natural_sort(list_to_sort: List[str]) -> List[str]:
+ """
+ Sorts a list of strings case insensitively as well as numerically.
+
+ For example: ['a1', 'A2', 'a3', 'A11', 'a22']
+
+ To sort a list in place, don't call this method, which makes a copy. Instead, do this:
+
+ my_list.sort(key=natural_keys)
+
+ :param list_to_sort: the list being sorted
+ :return: the list sorted naturally
+ """
+ return sorted(list_to_sort, key=natural_keys)