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() - Return part of a string
  • stristr() - 대소문자를 구분하지 않는 strstr
  • strcmp() - 바이너리 안전 문자열 비교
  • strncmp() - 처음 n 문자의 바이너리 안전 문자열 비교
  • strncasecmp() - 대소문자 구분 없는 처음 n 문자의 바이너리 안전 문자열 비교
  • strnatcasecmp() - "자연순" 알고리즘을 이용한 대소문자 구분 없는 문자열 비교
  • strstr() - 문자열이 처음으로 나오는 부분을 찾습니다
  • natsort() - "자연순" 알고리즘으로 배열 정렬
  • natcasesort() - "자연순" 알고리즘으로 대소문자를 구분하지 않고 배열 정렬

add a note add a note

User Contributed Notes 4 notes

up
7
in dot games dot mq at gmail dot com
8 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
-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
-4
spamspamspam at gmx dot com
6 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