case-insensitive list sorting, without lowercasing the result?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Case-insensitive sorting does not require you to lowercase the actual strings in the result. The usual technique is to sort by a transformed comparison key while returning the original values unchanged.
In Python, that means giving sorted or list.sort a key function. The sort compares the key values, but the original strings remain intact.
Sort by a Lowercased or Casefolded Key
A simple solution is:
This produces a case-insensitive order while preserving the original capitalization in the output.
Why does this work
sorted does not replace the list elements with the key values. It uses the key only for comparison. So "Banana" stays "Banana"; it is merely compared as if it were case-normalized.
str.casefold is usually a better default than str.lower for case-insensitive text comparison because it is designed for more aggressive Unicode-aware case normalization.
sorted Versus In-Place sort
If you want a new list, use sorted:
If you want to sort the existing list in place, use:
Both preserve the original strings. The difference is whether you want a new list object or to mutate the existing list.
Stable Sorting and Tie Behavior
Python's sort is stable. That means if two strings compare equal under the key, their original relative order is preserved.
Example:
Because "alice" and "ALICE" have the same casefolded key, their original order is preserved.
If you want a deterministic secondary tie-breaker, use a tuple key:
Now the case-insensitive form decides the main order, and the original string decides ties.
That extra tie-breaker is useful when you want repeated runs, tests, or serialized output to come out in the same order every time, even when several values differ only by case.
Why Not Lowercase the List First
A common bad approach is to transform the list before sorting:
That destroys the original capitalization, which is exactly what you said you wanted to keep. The whole point of the key parameter is that it lets comparison use transformed values without changing the actual elements.
So if the requirement is "sort without lowercasing the result," the key argument is the right abstraction.
Locale and International Text
For ordinary English-like text, str.casefold is often enough. If you need locale-aware collation rules for human-facing international sorting, simple case folding may not fully match user expectations.
In those cases, you may need locale-specific tools rather than plain lexicographic comparison. But for many application-level tasks, casefold is the best built-in starting point.
Common Pitfalls
The most common mistake is lowercasing the data itself instead of lowercasing only the comparison key.
Another mistake is using lower by habit when casefold would be the safer case-insensitive choice.
A third issue is being surprised when strings that differ only by case keep their original relative order. That is Python's stable sort doing exactly what it should do.
Summary
- Use
sorted(items, key=str.casefold)for case-insensitive sorting that preserves original strings. - The
keyfunction affects comparison, not the returned values. - Use
list.sort(key=...)if you want in-place sorting instead of a new list. - Python sorting is stable, so equal keys keep their original order.
- For most text,
casefoldis a better default thanlowerfor case-insensitive sorting.

