PHP 8.3.4 Released!

strnatcmp

(PHP 4, PHP 5, PHP 7, PHP 8)

strnatcmpComparaison de chaînes avec l'algorithme d'"ordre naturel"

Description

strnatcmp(string $string1, string $string2): int

Implémente l'algorithme de comparaison qui ordonne les chaînes tel qu'un homme le ferait. Notez que cette comparaison est sensible à la casse.

Liste de paramètres

string1

La première chaîne.

string2

La seconde chaîne.

Valeurs de retour

De la même façon que les autres fonctions comparant deux chaînes, la fonction retourne -1 si string1 est inférieure à string2; 1 si string1 est supérieure à string2, et 0 si les deux chaînes sont égales.

Historique

Version Description
8.2.0 Cette fonction retourne désormais -1 ou 1, alors qu'auparavant elle renvoyait un nombre négatif ou positif.

Exemples

Un exemple de la différence de traitement avec l'algorithme standard est présenté ci-dessous :

<?php
$arr1
= $arr2 = array("img12.png", "img10.png", "img2.png", "img1.png");
echo
"Tri de chaînes standard\n";
usort($arr1, "strcmp");
print_r($arr1);
echo
"\nTri de chaînes \"ordre naturel\"\n";
usort($arr2, "strnatcmp");
print_r($arr2);
?>

L'exemple ci-dessus va afficher :

Tri de chaînes standard
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

Tri de chaînes "ordre naturel"
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img10.png
    [3] => img12.png
)
Pour plus de détails, reportez-vous à » Natural Order String Comparison de Martin Pool (en anglais).

Voir aussi

  • preg_match() - Effectue une recherche de correspondance avec une expression rationnelle standard
  • strcasecmp() - Comparaison insensible à la casse de chaînes binaires
  • substr() - Retourne un segment de chaîne
  • stristr() - Version insensible à la casse de strstr
  • strcmp() - Comparaison binaire de chaînes
  • strncmp() - Comparaison binaire des n premiers caractères
  • strncasecmp() - Compare en binaire des chaînes de caractères
  • strnatcasecmp() - Comparaison de chaînes avec l'algorithme d'"ordre naturel" (insensible à la casse)
  • strstr() - Trouve la première occurrence dans une chaîne
  • natsort() - Trie un tableau avec l'algorithme à "ordre naturel"
  • natcasesort() - Trie un tableau avec l'algorithme à "ordre naturel" insensible à la casse

add a note

User Contributed Notes 4 notes

up
7
in dot games dot mq at gmail dot com
7 years ago
Can also be used with combination of a compare for an array nested value, like

<?php
$array
= array(
"city" => "xyz",
"names" => array(
array(
"name" => "Ana2",
"id" => 1
) ,
array(
"name" => "Ana1",
"id" => 2
)
)
);
usort($array["names"], function ($a, $b) { return strnatcmp($a['name'], $b['name']);} );
up
2
thomas at uninet dot se
17 years ago
There seems to be a bug in the localization for strnatcmp and strnatcasecmp. I searched the reported bugs and found a few entries which were up to four years old (but the problem still exists when using swedish characters).

These functions might work instead.
<?php
function _strnatcasecmp($left, $right) {
return
_strnatcmp(strtolower($left), strtolower($right));
}

function
_strnatcmp($left, $right) {
while((
strlen($left) > 0) && (strlen($right) > 0)) {
if(
preg_match('/^([^0-9]*)([0-9].*)$/Us', $left, $lMatch)) {
$lTest = $lMatch[1];
$left = $lMatch[2];
} else {
$lTest = $left;
$left = '';
}
if(
preg_match('/^([^0-9]*)([0-9].*)$/Us', $right, $rMatch)) {
$rTest = $rMatch[1];
$right = $rMatch[2];
} else {
$rTest = $right;
$right = '';
}
$test = strcmp($lTest, $rTest);
if(
$test != 0) {
return
$test;
}
if(
preg_match('/^([0-9]+)([^0-9].*)?$/Us', $left, $lMatch)) {
$lTest = intval($lMatch[1]);
$left = $lMatch[2];
} else {
$lTest = 0;
}
if(
preg_match('/^([0-9]+)([^0-9].*)?$/Us', $right, $rMatch)) {
$rTest = intval($rMatch[1]);
$right = $rMatch[2];
} else {
$rTest = 0;
}
$test = $lTest - $rTest;
if(
$test != 0) {
return
$test;
}
}
return
strcmp($left, $right);
}
?>

The code is not optimized. It was just made to solve my problem.
up
-1
chris at ocproducts dot com
6 years ago
This function has some interesting behaviour on strings consisting of mixed numbers and letters.

One may expect that such a mixed string would be treated as alpha-numeric, but that is not true.

var_dump(strnatcmp('23','123')); →
int(-1)
As expected, 23<123 (even though first digit is higher, overall number is smaller)

var_dump(strnatcmp('yz','xyz')); →
int(1)
As expected, yz>xyz (string comparison, irregardless of string length)

var_dump(strnatcmp('2x','12y')); →
int(-1)
Remarkable, 2x<12y (does a numeric comparison)

var_dump(strnatcmp('20x','12y'));
int(1)
Remarkable, 20x>12y (does a numeric comparison)

It seems to be splitting what is being compared into runs of numbers and letters, and then comparing each run in isolation, until it has an ordering difference.
up
-4
spamspamspam at gmx dot com
5 years ago
Some more remarkable outcomes:

var_dump(strnatcmp("0.15m", "0.2m"));
int(1)

var_dump(strnatcmp("0.15m", "0.20m"));
int(-1)

It's not about localisation:

var_dump(strnatcmp("0,15m", "0,2m"));
int(1)

var_dump(strnatcmp("0,15m", "0,20m"));
int(-1)
To Top