Сравнение нечувствительных к регистру строк

Я хотел бы сравнить две переменные, чтобы убедиться, что они одинаковые, но я хочу, чтобы это сравнение было нечувствительным к регистру.

Например, это будет чувствительным к регистру:

if($var1 == $var2){ ... } 

Но я хочу, чтобы это было нечувствительным к регистру, как бы я к этому подошел?

Это довольно просто; вам просто нужно вызвать strtolower() для обеих переменных.

Если вам нужно иметь дело с Unicode или международными наборами символов, вы можете использовать mb_strtolower() .

Обратите внимание, что в других ответах предлагается использовать strcasecmp() , которая не обрабатывает многобайтовые символы, поэтому результаты для любой строки UTF-8 будут фиктивными.

strcasecmp() возвращает 0, если строки одинаковы (кроме вариантов case), поэтому вы можете использовать:

 if (strcasecmp($var1, $var2) == 0) { } 

Если ваша строка находится в одной байтовой кодировке, это просто:

 if(strtolower($var1) === strtolower($var2)) 

Если ваша строка UTF-8, вы должны учитывать сложность Unicode: от-нижний регистр и от верхнего предела – не биективные функции, т. Е. Если у вас есть строчный символ, преобразуйте его в верхний регистр и преобразуйте он возвращается в нижний регистр, вы можете не иметь ту же самую кодовую точку (и то же самое верно, если вы начинаете с символа верхнего регистра).

Например

  • «İ» ( Latin Capital Letter I with Dot Above, U+0130 ) является символом верхнего регистра с Latin Small Letter I, U+0069 «i» ( Latin Small Letter I, U+0069 ) как ее нижний регистр – и верхний регистр «i» вариант – это «я» ( Latin Capital Letter I, U+0049 ).
  • «ı» ( Latin Small Letter Dotless I, U+0131 ) является строчным символом с Latin Capital Letter I, U+0049 «I» ( Latin Capital Letter I, U+0049 ) в качестве ее варианта с верхним регистром, а вариант нижнего регистра «I» – «i» ( Latin Small Letter I, U+0069 )

Итак, mb_strtolower('ı') === mb_strtolower('i') возвращает false, хотя у них одинаковый символ верхнего регистра. Если вам действительно нужна функция сравнения строк без учета регистра, вам нужно сравнить с верхним регистром и версией в нижнем регистре:

 if(mb_strtolower($string1) === mb_strtolower($string2) || mb_strtoupper($string1) === mb_strtoupper($string2)) 

Я выполнил запрос к базе данных Unicode с https://codepoints.net ( https://dumps.codepoints.net ), и я нашел 180 пунктов кода, для которых я нашел другой символ, когда принимал символы нижнего регистра в нижнем регистре нижнего регистра и 8 кодовых точках, для которых я нашел другой символ, когда принимал верхний регистр верхнего регистра символов в верхнем регистре

Но становится все хуже : тот же самый графем-кластер, который видит пользователь, может иметь несколько способов его кодирования: «ä» может быть представлен как Latin Small Letter a with Diaeresis (U+00E4) или как Latin Small Letter A (U+0061) и Combining Diaeresis (U+0308) – и если вы сравните их на уровне байтов, это не вернет истину!

Но в Unicode есть решение для этого: нормализация ! Существует четыре различных формы: NFC, NFD, NFKC, NFKD. Для сравнения строк NFC и NFD эквивалентны, а NFKC и NFKD эквивалентны. Я бы взял NFKC, поскольку он короче NFKD, а «ff» ( Latin Small Ligature ff, U+FB00 ) преобразуется в два нормальных «f» (но 2⁵ также будет расширен до 25 …).

Результирующая функция будет:

 function mb_is_string_equal_ci($string1, $string2) { $string1_normalized = Normalizer::normalize($string1, Normalizer::FORM_KC); $string2_normalized = Normalizer::normalize($string2, Normalizer::FORM_KC); return mb_strtolower($string1_normalized) === mb_strtolower($string2_normalized) || mb_strtoupper($string1_normalized) === mb_strtoupper($string2_normalized); } 

Пожалуйста, обратите внимание:

  • вам нужен пакет intl для нормализатора
  • вы должны оптимизировать эту функцию, сначала проверив, насколько они равны ^^
  • вы можете использовать NFC вместо NFKC, потому что NFKC удаляет слишком много различий в форматировании для вашего вкуса
  • вы должны решить для себя, если вам действительно нужна вся эта сложность или если вы предпочитаете более простой вариант этой функции
 if(strtolower($var1) == strtolower($var2)){ } 

Используйте strcasecmp .

Почему нет:

 if(strtolower($var1) == strtolower($var2)){ }