Я хотел бы сравнить две переменные, чтобы убедиться, что они одинаковые, но я хочу, чтобы это сравнение было нечувствительным к регистру.
Например, это будет чувствительным к регистру:
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); }
Пожалуйста, обратите внимание:
if(strtolower($var1) == strtolower($var2)){ }
Используйте strcasecmp .
Почему нет:
if(strtolower($var1) == strtolower($var2)){ }