string sorting
numbers in strings
sorting algorithms
data handling
programming tips

Sort on a string that may contain a number

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

If a string may contain a number, plain lexicographic sorting is often not what people expect. For example, "file10" comes before "file2" in normal string order because "1" is compared before "2" character by character. The usual fix is natural sorting, where digit runs are compared numerically instead of as raw text.

Why Plain String Sorting Looks Wrong

Standard sorting treats everything as characters:

python
items = ["file12", "file1", "file3", "file10"]
print(sorted(items))

Output:

text
['file1', 'file10', 'file12', 'file3']

That is correct lexicographic order, but it is not what most humans mean by "sort these filenames."

Natural Sorting with a Custom Key

The standard pattern is to split each string into text parts and numeric parts, then convert numeric parts to integers for comparison.

python
1import re
2
3def natural_key(text):
4    parts = re.split(r"(\d+)", text)
5    return [int(part) if part.isdigit() else part.lower() for part in parts]
6
7
8items = ["file12", "file1", "file3", "file10"]
9print(sorted(items, key=natural_key))

Output:

text
['file1', 'file3', 'file10', 'file12']

This works because the sort key for "file10" becomes something like ["file", 10, ""] instead of just "file10".

Handling Strings Without Numbers

The nice part about this approach is that it also works for strings with no digits at all.

python
items = ["alpha", "file12", "file2", "beta"]
print(sorted(items, key=natural_key))

Strings without numbers simply produce keys made of text fragments, so they still participate in the same ordering logic.

Sorting by a Possibly Numeric Entire String

Sometimes the string is either fully numeric or fully text, such as:

python
items = ["20", "3", "apple", "10", "banana"]

In that case, you might want a different rule. For example, place numeric strings first in numeric order, then text strings alphabetically:

python
1def mixed_key(text):
2    if text.isdigit():
3        return (0, int(text))
4    return (1, text.lower())
5
6
7items = ["20", "3", "apple", "10", "banana"]
8print(sorted(items, key=mixed_key))

Output:

text
['3', '10', '20', 'apple', 'banana']

This is a slightly different problem than embedded-number sorting, so it helps to decide which behavior you actually want.

Sorting Objects by a String Field

Often you are not sorting raw strings but records that contain a label. The same natural key can be applied to one field.

python
1rows = [
2    {"name": "item20", "value": 1},
3    {"name": "item3", "value": 2},
4    {"name": "item11", "value": 3},
5]
6
7rows.sort(key=lambda row: natural_key(row["name"]))
8print(rows)

This is useful for table rows, API data, filenames, and UI lists that carry extra metadata.

Using a Library

If you need natural sorting often, a dedicated library such as natsort can save time and cover more edge cases.

python
1from natsort import natsorted
2
3items = ["file12", "file1", "file3", "file10"]
4print(natsorted(items))

That is often the most readable production solution if external dependencies are acceptable.

Things to Decide Up Front

Natural sorting sounds simple, but there are policy choices:

  • Should comparison be case-sensitive
  • Should leading zeros matter
  • How should negative numbers be handled
  • What about decimal points or version strings such as "v1.10.2"

The regex-based key above handles many common filename-style cases, but more specialized strings may need a custom parser.

Common Pitfalls

One common mistake is assuming built-in string sorting will automatically treat digits as numbers. It will not.

Another issue is writing a key that converts only the first number in the string. That may work for simple names but fail for version-like strings with multiple numeric segments.

Developers also sometimes compare strings case-sensitively without meaning to, which can put uppercase and lowercase values in surprising positions.

Finally, be clear about whether the entire string may be numeric or whether numbers are embedded inside otherwise textual labels. Those are related but different sorting problems.

Summary

  • Plain string sorting is lexicographic, not numeric.
  • Use a natural-sort key when strings contain embedded numbers.
  • Split text into digit and non-digit parts, and convert digit parts to integers.
  • If only some strings are entirely numeric, design a key that handles numeric and text cases explicitly.
  • For repeated use, a library such as natsort can be cleaner than rolling your own every time.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.