def natsort_keygen(key=None, alg=0, **_kwargs): """\ Generate a key to sort strings and numbers naturally. Generate a key to sort strings and numbers naturally, not lexicographically. This key is designed for use as the `key` argument to functions such as the `sorted` builtin. The user may customize the generated function with the arguments to `natsort_keygen`, including an optional `key` function which will be called before the `natsort_key`. Parameters ---------- key : callable, optional A key used to manipulate the input value before parsing for numbers. It is **not** applied recursively. It should accept a single argument and return a single value. alg : ns enum, optional This option is used to control which algorithm `natsort` uses when sorting. For details into these options, please see the :class:`ns` class documentation. The default is `ns.INT`. Returns ------- out : function A wrapped version of the `natsort_key` function that is suitable for passing as the `key` argument to functions such as `sorted`. See Also -------- natsorted Examples -------- `natsort_keygen` is a convenient way to create a custom key to sort lists in-place (for example). Calling with no objects will return a plain `natsort_key` instance:: >>> a = ['num5.10', 'num-3', 'num5.3', 'num2'] >>> a.sort(key=natsort_keygen(alg=ns.REAL)) >>> a [{u}'num-3', {u}'num2', {u}'num5.10', {u}'num5.3'] """ return partial(_natsort_key, key=key, alg=_args_to_enum(**_kwargs) | alg)
def index_natsorted(seq, key=None, reverse=False, alg=0, **_kwargs): """\ Return the list of the indexes used to sort the input sequence. Sorts a sequence naturally, but returns a list of sorted the indexes and not the sorted list. This list of indexes can be used to sort multiple lists by the sorted order of the given sequence. Parameters ---------- seq : iterable The sequence to sort. key : callable, optional A key used to determine how to sort each element of the sequence. It is **not** applied recursively. It should accept a single argument and return a single value. reverse : {{True, False}}, optional Return the list in reversed sorted order. The default is `False`. alg : ns enum, optional This option is used to control which algorithm `natsort` uses when sorting. For details into these options, please see the :class:`ns` class documentation. The default is `ns.INT`. Returns ------- out : tuple The ordered indexes of the sequence. See Also -------- natsorted order_by_index Examples -------- Use index_natsorted if you want to sort multiple lists by the sorted order of one list:: >>> a = ['num3', 'num5', 'num2'] >>> b = ['foo', 'bar', 'baz'] >>> index = index_natsorted(a) >>> index [2, 0, 1] >>> # Sort both lists by the sort order of a >>> order_by_index(a, index) [{u}'num2', {u}'num3', {u}'num5'] >>> order_by_index(b, index) [{u}'baz', {u}'foo', {u}'bar'] """ alg = _args_to_enum(**_kwargs) | alg if key is None: newkey = itemgetter(1) else: def newkey(x): return key(itemgetter(1)(x)) # Pair the index and sequence together, then sort by element index_seq_pair = [[x, y] for x, y in enumerate(seq)] try: index_seq_pair.sort(reverse=reverse, key=natsort_keygen(newkey, alg=alg)) except TypeError as e: # pragma: no cover # In the event of an unresolved "unorderable types" error # attempt to sort again, being careful to prevent this error. if 'unorderable types' in str(e): index_seq_pair.sort(reverse=reverse, key=natsort_keygen(newkey, alg=alg | ns.TYPESAFE)) else: # Re-raise if the problem was not "unorderable types" raise return [x for x, _ in index_seq_pair]
def natsorted(seq, key=None, reverse=False, alg=0, **_kwargs): """\ Sorts a sequence naturally. Sorts a sequence naturally (alphabetically and numerically), not lexicographically. Returns a new copy of the sorted sequence as a list. Parameters ---------- seq : iterable The sequence to sort. key : callable, optional A key used to determine how to sort each element of the sequence. It is **not** applied recursively. It should accept a single argument and return a single value. reverse : {{True, False}}, optional Return the list in reversed sorted order. The default is `False`. alg : ns enum, optional This option is used to control which algorithm `natsort` uses when sorting. For details into these options, please see the :class:`ns` class documentation. The default is `ns.INT`. Returns ------- out: list The sorted sequence. See Also -------- natsort_keygen : Generates the key that makes natural sorting possible. realsorted : A wrapper for ``natsorted(seq, alg=ns.REAL)``. humansorted : A wrapper for ``natsorted(seq, alg=ns.LOCALE)``. index_natsorted : Returns the sorted indexes from `natsorted`. Examples -------- Use `natsorted` just like the builtin `sorted`:: >>> a = ['num3', 'num5', 'num2'] >>> natsorted(a) [{u}'num2', {u}'num3', {u}'num5'] """ alg = _args_to_enum(**_kwargs) | alg try: return sorted(seq, reverse=reverse, key=natsort_keygen(key, alg=alg)) except TypeError as e: # pragma: no cover # In the event of an unresolved "unorderable types" error # for string to number type comparisons (not str/bytes), # attempt to sort again, being careful to prevent this error. r = re.compile(r'(?:str|bytes)\(\) [<>] (?:str|bytes)\(\)') if 'unorderable types' in str(e) and not r.search(str(e)): return sorted(seq, reverse=reverse, key=natsort_keygen(key, alg=alg | ns.TYPESAFE)) else: # Re-raise if the problem was not "unorderable types" raise
def natsort_key(val, key=None, alg=0, **_kwargs): """Undocumented, kept for backwards-compatibility.""" msg = "natsort_key is deprecated as of 3.4.0, please use natsort_keygen" warn(msg, DeprecationWarning) return _natsort_key(val, key, _args_to_enum(**_kwargs) | alg)