strnatcmp

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

strnatcmpComparações de strings usando um algoritmo de "ordem natural"

Descrição

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

Esta função implementa um algoritmo de comparação que ordena strings alfanuméricas da mesma forma que um ser humano faria, o que é descrito como "ordenação natural". Observe que esta comparação é sensível a maiúsculas/minúsculas.

Parâmetros

string1

A primeira string.

string2

A segunda string.

Valor Retornado

Da mesma forma que outras funções de comparação de strings, esta retorna -1 se string1 estiver abaixo de string2; 1 se string1 estiver acima de string2, e 0 se elas forem iguais.

Registro de Alterações

Versão Descrição
8.2.0 Esta função agora retorna -1 ou 1, onde anteriormente retornava um número negativo ou positivo.

Exemplos

Um exemplo da diferença entre este algoritmo e os algoritmos de ordenação de strings comuns (usados em strcmp()) pode ser visto abaixo:

<?php
$arr1
= $arr2 = array("img12.png", "img10.png", "img2.png", "img1.png");
echo
"Comparação padrão de strings\n";
usort($arr1, "strcmp");
print_r($arr1);
echo
"\nComparação de strings em ordem natural\n";
usort($arr2, "strnatcmp");
print_r($arr2);
?>

O exemplo acima produzirá:

Comparação padrão de strings
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

Comparação de strings em ordem natural
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img10.png
    [3] => img12.png
)
Para mais informação, consulte a página » Comparação de String em Ordem Natural, de Martin Pool.

Veja Também

  • preg_match() - Realiza uma correspondência com expressão regular
  • strcasecmp() - Comparação binária segura de strings insensível a maiúsculas/minúsculas
  • substr() - Retorna parte de uma string
  • stristr() - strstr insensível a maiúsculas/minúsculas
  • strcmp() - Comparação binária segura de strings
  • strncmp() - Comparação de strings segura para binários dos primeiros n caracteres
  • strncasecmp() - Comparação binária de strings, insensível a maiúsculas/minúsculas, dos primeiros n caracteres
  • strnatcasecmp() - Comparação de strings insensível a maiúsculas/minúsculas usando o algoritmo de "ordem natural"
  • strstr() - Encontra a primeira ocorrência de uma string
  • natsort() - Ordena um array utilizando o algoritmo de "ordem natural"
  • natcasesort() - Ordena um array utilizando o algoritmo da "ordem natural" sem diferenciar maiúsculas e minúsculas

add a note

User Contributed Notes 4 notes

up
6
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
18 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
0
chris at ocproducts dot com
7 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
-3
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