natural_sort.py 949 B

1234567891011121314151617181920
  1. """Natural (numeric-aware) string sorting, e.g. "Drybox 2" before "Drybox 10"."""
  2. import re
  3. _CHUNK_RE = re.compile(r"(\d+)")
  4. def natural_sort_key(value: str) -> tuple:
  5. """Sort key that orders embedded numbers by value, not lexicographically.
  6. A plain string sort puts "Drybox 10" before "Drybox 2" (character by
  7. character, "1" < "2"). Splitting into alternating text/digit runs and
  8. comparing the digit runs as integers instead gets "Drybox 2" before
  9. "Drybox 10", without assuming every name follows a fixed "prefix N"
  10. shape. `_CHUNK_RE.split` always yields text chunks at even indices and
  11. digit chunks at odd indices for any input, so the type at a given index
  12. is consistent across every key this function produces — two keys can be
  13. compared without ever hitting a str-vs-int mismatch mid-tuple.
  14. """
  15. return tuple(int(chunk) if chunk.isdigit() else chunk.lower() for chunk in _CHUNK_RE.split(value))