• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • strnatcmp()

    (PHP 4, PHP 5, PHP 7)

    使用自然排序算法比较字符串

    说明

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

    该函数实现了以人类习惯对数字型字符串进行排序的比较算法,这就是“自然顺序”。注意该比较区分大小写。

    参数

    $str1

    第一个字符串。

    $str2

    第二个字符串。

    返回值

    与其他字符串比较函数类似,如果$str1小于$str2返回< 0;如果$str1大于$str2返回> 0;如果两者相等,返回 0。

    范例

    下面的例子展示了该算法与计算机常规字符串比较算法(strcmp()所使用的)的区别:

    <?php
    $arr1 = $arr2 = array("img12.png", "img10.png", "img2.png", "img1.png");
    echo "Standard string comparison\n";
    usort($arr1, "strcmp");
    print_r($arr1);
    echo "\nNatural order string comparison\n";
    usort($arr2, "strnatcmp");
    print_r($arr2);
    ?>

    以上例程会输出:

    Standard string comparison
    Array
    (
        [0] => img1.png
        [1] => img10.png
        [2] => img12.png
        [3] => img2.png
    )
    Natural order string comparison
    Array
    (
        [0] => img1.png
        [1] => img2.png
        [2] => img10.png
        [3] => img12.png
    )
    
    更多信息,参见:Martin Pool 的»自然顺序的字符串比较page.

    参见

    • preg_match()执行匹配正则表达式
    • strcasecmp()二进制安全比较字符串(不区分大小写)
    • substr()返回字符串的子串
    • stristr()strstr 函数的忽略大小写版本
    • strcmp()二进制安全字符串比较
    • strncmp()二进制安全比较字符串开头的若干个字符
    • strncasecmp()二进制安全比较字符串开头的若干个字符(不区分大小写)
    • strnatcasecmp()使用“自然顺序”算法比较字符串(不区分大小写)
    • strstr()查找字符串的首次出现
    • natsort()用“自然排序”算法对数组排序
    • natcasesort()用“自然排序”算法对数组进行不区分大小写字母的排序
    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.
    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.
    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']);} );
    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)
    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";
       }
    }
    ?>

    上篇:strnatcasecmp()

    下篇:strncasecmp()