PHP 7.2.0 Release Candidate 2 Released

strnatcmp

(PHP 4, PHP 5, PHP 7)

strnatcmp"自然順"アルゴリズムにより文字列比較を行う

説明

int strnatcmp ( string $str1 , string $str2 )

この関数は、人間が行うような手法でアルファベットまたは数字の 文字列の順序を比較するアルゴリズムを実装します。この手法は、"自然順" と言われます。 この比較は、大文字小文字を区別することに注意してください。

パラメータ

str1

最初の文字列。

str2

次の文字列。

返り値

他の文字列比較関数と同様に、この関数は、 str1str2 より小さいに場合に < 0、str1str2 より大きい場合に > 0 、等しい場合に 0 を返します。

このアルゴリズムと (strcmp() を使用した) 通常のコンピュータ文字列ソートの間の違いの例を次に示します。

<?php
$arr1 
$arr2 = array("img12.png""img10.png""img2.png""img1.png");
echo 
"標準の文字列比較\n";
usort($arr1"strcmp");
print_r($arr1);
echo 
"\n自然順での文字列比較\n";
usort($arr2"strnatcmp");
print_r($arr2);
?>

上の例の出力は以下となります。

標準の文字列比較
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

自然順での文字列比較
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img10.png
    [3] => img12.png
)
詳細な情報については、Martin Pool の » 自然順文字列比較 のページを参照ください。

参考

  • preg_match() - 正規表現によるマッチングを行う
  • strcasecmp() - 大文字小文字を区別しないバイナリセーフな文字列比較を行う
  • substr() - 文字列の一部分を返す
  • stristr() - 大文字小文字を区別しない strstr
  • strcmp() - バイナリセーフな文字列比較
  • strncmp() - 最初の n 文字についてバイナリセーフな文字列比較を行う
  • strncasecmp() - バイナリセーフで大文字小文字を区別しない文字列比較を、最初の n 文字について行う
  • strnatcasecmp() - "自然順"アルゴリズムにより大文字小文字を区別しない文字列比較を行う
  • strstr() - 文字列が最初に現れる位置を見つける
  • natsort() - "自然順"アルゴリズムで配列をソートする
  • natcasesort() - 大文字小文字を区別しない"自然順"アルゴリズムを用いて配列をソートする

add a note add a note

User Contributed Notes 4 notes

up
4
thomas at uninet dot se
11 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
in dot games dot mq at gmail dot com
9 months 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
-1
chris at ocproducts dot com
4 months 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
-51
Zero
6 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