1

Strnatcasecmp: примеры (PHP)

Функция strnatcasecmp для естественного сравнения строк в PHP
Раздел: Работа со строками
strnatcasecmp(string string1, string string2): int

Функция strnatcasecmp в PHP

Функция strnatcasecmp в PHP служит для сравнения двух строк по алгоритму «естественного порядка» с игнорированием регистра символов. Этот метод сравнения полезен, когда строки содержат числа, так как он учитывает их числовое значение, а не лексикографический порядок, что приводит к более интуитивно понятным для человека результатам сортировки. Функция часто применяется для сортировки списков файлов, названий товаров с артикулами или любых данных, где числовая часть является значимой.

Аргументы функции

Функция принимает два обязательных аргумента:

  • string1 (string): Первая строка для сравнения.
  • string2 (string): Вторая строка для сравнения.

Функция возвращает целое число: меньше 0, если string1 меньше string2; больше 0, если string1 больше string2; и 0, если строки равны с учётом естественного порядка и без регистра.

Примеры использования strnatcasecmp

Базовое сравнение строк с числами

Стандартное сравнение строк (strcmp) анализирует символы по кодам ASCII, в то время как естественное сравнение распознает числовые последовательности.

<?
$result1 = strnatcasecmp('Image2.jpg', 'Image10.jpg');
$result2 = strcasecmp('Image2.jpg', 'Image10.jpg');
echo "strnatcasecmp: $result1\n";
echo "strcasecmp: $result2\n";
?>
strnatcasecmp: -1
strcasecmp: 1

Первый результат (-1) указывает, что 'Image2.jpg' меньше 'Image10.jpg' (2 < 10), что логично. Второй результат (1) показывает, что обычное сравнение считает 'Image2.jpg' больше, потому что символ '2' идет после символа '1'.

Игнорирование регистра
<?
$result = strnatcasecmp('APPLE', 'apple');
echo $result;
?>
0

Функция возвращает 0, так как строки идентичны при игнорировании регистра букв.

Сравнение сложных строк
<?
$result = strnatcasecmp('release-1.2.3', 'release-1.12.0');
echo $result;
?>
-1

Здесь 1.2.3 меньше, чем 1.12.0, потому что 2 < 12.

Похожие функции в PHP

  • strnatcmp: Проводит аналогичное естественное сравнение, но является регистрозависимой. Предпочтительна, когда различие между заглавными и строчными буквами важно.
  • strcasecmp: Бинарно безопасное сравнение строк без учета регистра, но не использующее алгоритм естественного порядка. Подходит для простого регистронезависимого сравнения, где нет числовых данных.
  • strcmp: Бинарно безопасное регистрозависимое сравнение. Базовый инструмент для точного сравнения строк.
  • similar_text, levenshtein: Функции для оценки схожести строк, а не для их упорядочивания. Используются в задачах нечеткого поиска.

Выбор функции зависит от задачи: для сортировки названий файлов или версий лучше подходит strnatcasecmp; для точного сравнения паролей или ключей — strcmp.

Типичные ошибки

Неправильная интерпретация возвращаемого значения

Частая ошибка — ожидание булевых true/false. Функция возвращает целое число.

<?
// Неправильно:
if (strnatcasecmp('строка1', 'строка2')) {
    echo 'Строки не равны';
}
// Такое условие сработает даже при -1, что трактуется как true.
// Правильно:
if (strnatcasecmp('строка1', 'строка2') !== 0) {
    echo 'Строки не равны';
}
?>
Путаница с порядком аргументов

Возвращаемое значение указывает на отношение первого аргумента ко второму. Если результат меньше нуля, первая строка меньше второй. Это важно учитывать при использовании в пользовательских функциях сортировки.

<?
$array = ['img12.png', 'img2.png', 'img1.png'];
usort($array, 'strnatcasecmp'); // Сортирует по возрастанию
print_r($array);
?>
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img12.png
)

Изменения в последних версиях PHP

Начиная с PHP 8.0.0, функция strnatcasecmp теперь выбрасывает исключение TypeError при передаче не строковых аргументов, в отличие от предыдущих версий, где такие аргументы преобразовывались в строки или вызывали предупреждение. Это изменение соответствует общей политике строгой типизации в PHP 8.

<?
// PHP 7 и ранее: возможно предупреждение, но сравнение продолжится.
// PHP 8.0.0 и выше: фатальная ошибка TypeError.
try {
    $result = strnatcasecmp('text', []);
} catch (TypeError $e) {
    echo $e->getMessage();
}
?>
strnatcasecmp(): Argument #2 ($string2) must be of type string, array given

Расширенные примеры применения

Сортировка многомерного массива по ключу
Пример php
<?
$products = [
    ['name' => 'Widget v2', 'sku' => 'item-2'],
    ['name' => 'Widget v12', 'sku' => 'item-12'],
    ['name' => 'widget v1', 'sku' => 'item-1'],
];

usort($products, function($a, $b) {
    return strnatcasecmp($a['name'], $b['name']);
});

print_r($products);
?>
Array
(
    [0] => Array
        (
            [name] => widget v1
            [sku] => item-1
        )
    [1] => Array
        (
            [name] => Widget v2
            [sku] => item-2
        )
    [2] => Array
        (
            [name] => Widget v12
            [sku] => item-12
        )
)
Обработка пользовательского ввода при фильтрации

Сравнение введенного пользователем поискового запроса с игнорированием регистра и учетом чисел в названиях.

Пример php
<?
$searchTerm = 'model 2023';
$databaseEntries = ['Model 2022', 'MODEL 2023', 'Model 2021', 'model 2024'];

$matches = array_filter($databaseEntries, function($entry) use ($searchTerm) {
    return strnatcasecmp($entry, $searchTerm) === 0;
});

print_r($matches);
?>
Array
(
    [1] => MODEL 2023
)
Интеграция в пользовательскую функцию сортировки для объектов
Пример php
<?
class Document {
    public function __construct(public string $title) {}
}

$docs = [
    new Document('Report 10'),
    new Document('report 2'),
    new Document('Report 1'),
];

usort($docs, function($a, $b) {
    return strnatcasecmp($a->title, $b->title);
});

foreach ($docs as $doc) {
    echo $doc->title . "\n";
}
?>
Report 1
report 2
Report 10

Аналоги функции в других языках

Strnatcasecmp в Python

В стандартной библиотеке нет прямой аналогии. Для естественной сортировки без учета регистра используют комбинацию str.casefold и библиотеки natsort или собственную реализацию.

import natsort
list1 = ['Image2.jpg', 'Image10.jpg', 'image1.jpg']
sorted_list = natsort.natsorted(list1, alg=natsort.IC)
print(sorted_list)
['image1.jpg', 'Image2.jpg', 'Image10.jpg']

Strnatcasecmp в Javascript

Аналогично, для естественной сортировки без учета регистра применяют сторонние библиотеки или Intl.Collator с числовым опцией.

const items = ['Image2.jpg', 'Image10.jpg', 'image1.jpg'];
const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
items.sort(collator.compare);
console.log(items);
['image1.jpg', 'Image2.jpg', 'Image10.jpg']

Strnatcasecmp в MySQL

Оператор сравнения строк не имеет встроенного естественного алгоритма. Обычно сортировку выполняют после извлечения данных в приложение.

PHP strnatcasecmp function comments

En
Strnatcasecmp Case insensitive string comparisons using a "natural order" algorithm