strnatcmp

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

strnatcmp Comparação de strings usando o algoritmo "natural order"

Descrição

strnatcmp ( string $str1 , string $str2 ) : int

Esta função implementa um algoritmo de comparação de strings alfanumérico do jeito que um ser humano faz, isto é descrito como "ordem natural". Um exemplo da diferença entre este algoritmo e os algoritmos regulares de ordenação (usado em strcmp()) pode ser visto abaixo:

<?php
$arr1 
$arr2 = array("img12.png","img10.png","img2.png","img1.png");
echo 
"Comparação de string padrão\n";
usort($arr1,"strcmp");
print_r($arr1);
echo 
"\nComparação usando ordem natural\n";
usort($arr2,"strnatcmp");
print_r($arr2);
?>
O código acima irá gerar a seguinte saída:
Comparação de string padrão
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

Comparação usando ordem natural
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img10.png
    [3] => img12.png
)
Para maiores informações veja: Martin Pool's » Natural Order String Comparison

Similar a outras funções de comparação de string, esta retorna < 0 se str1 é menor do que str2; > 0 se str1 é maior do que str2, e 0 se forem iguais.

Note que esta coparação diferencia maiúsculas e minúsculas.

Veja também ereg(), strcasecmp(), substr(), stristr(), strcmp(), strncmp(), strncasecmp(), strnatcasecmp(), strstr(), natsort() e natcasesort().

add a note add a note

User Contributed Notes 5 notes

up
1
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
3
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
-2
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)
up
-1
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
-58
Zero
13 years ago
If you want to compare $_SESSION variables to a string use this

<?php
if(isset($_SESSION['usertype']))
{   
     echo
"usertype " .$_SESSION['usertype'];
               
    
$ut = $_SESSION['usertype'];
               
     if(
strnatcmp($ut,"admin"))
     {
          echo
"hello admin";
     }
}
?>
To Top