strnatcmp

Compares two strings in human "natural" order, treating digit runs as numbers.

Signature
strnatcmp(string $string1, string $string2): int
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$string1stringThe first string.
$string2stringThe second string.

Return value

intA value less than 0 if string1 is less than string2, a value greater than 0 if string1 is greater than string2, and 0 if they are equal.

Changelog

  • PHP 8.2.0This function is no longer guaranteed to return strlen($string1) - strlen($string2) when string lengths are not equal, but may now return -1 or 1 instead.

strnatcmp() implements Martin Pool's "natural order" algorithm. It walks both strings together, comparing letters normally but comparing consecutive digits as a single number. That is why img2.png comes before img10.png, which a plain strcmp() gets backwards.

When to reach for it

Use it any time a list is going to be read by a person and the labels contain numbers: filenames, invoice references, exam question numbers, page names. Pass it to usort() as the comparison callback, or use natsort() if the keys must survive.

What trips people up

It is case sensitive, and uppercase letters sort before lowercase ones. strnatcmp('Item 10', 'item 9') is negative purely because I is byte 73 and i is byte 105 — the numbers never get compared. Use strnatcasecmp() when the case of your data is not under your control.

Treat the return value as a sign only. Since PHP 8.2 it usually returns -1, 0 or 1 rather than a difference, so any arithmetic on the result is unsafe.

Leading zeros are compared as fractional parts, so x007 ranks below x7 rather than equal to it.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Sort screenshot files img1.png, img2.png, img10.png into the order a person expects.
  • Order invoice or purchase-order references such as PO-9 and PO-100.
  • Sort simple dotted numbers like 1.2.10 and 1.9.0 where full version_compare semantics are not needed.

Frequently asked questions

What is the difference between strcmp and strnatcmp?

strcmp compares byte by byte, so "img10" sorts before "img2". strnatcmp compares each run of digits as a number, producing the order a human reader expects.

Is strnatcmp case sensitive?

Yes. Uppercase letters sort before lowercase ones, and the case difference is decided before any digits are compared. Use strnatcasecmp() for a case-insensitive comparison.

How do I sort an array in natural order in PHP?

Call usort($array, 'strnatcmp') for a reindexed list, or natsort($array) to sort in place while preserving the keys.

More examples

Case sensitivity bites first

The first call is negative even though 10 is larger than 9, because the uppercase I is compared before the digits are ever reached. The case-insensitive version gets it right. The sorted array shows the same effect: ITEM 2 and Item 10 group ahead of item 9 by case, not by number.

Example · php
<?php
var_dump(strnatcmp('Item 10', 'item 9'));     // int(-1)
var_dump(strnatcasecmp('Item 10', 'item 9')); // int(1)

$mixed = ['Item 10', 'item 9', 'ITEM 2'];
usort($mixed, 'strnatcmp');
print_r($mixed);

Sorting dotted numbers

Both calls produce 1.2.10, 1.9.0, 1.10.0 because each dotted segment is a clean digit run. They diverge as soon as a suffix like 1.10.0-beta appears, which version_compare ranks below 1.10.0 while strnatcmp ranks it above.

Example · php
<?php
$versions = ['1.10.0', '1.9.0', '1.2.10'];

usort($versions, 'strnatcmp');
print_r($versions);

usort($versions, 'version_compare');
print_r($versions);

Discussion

  • Be the first to comment on this lesson.