Сравнение нечувствительных к регистру строк
Я хотел бы сравнить две переменные, чтобы увидеть, являются ли они одинаковыми, но я хочу, чтобы это сравнение было нечувствительным к регистру.
Например, это будет чувствительным к регистру:
if($var1 == $var2){
...
}
Но я хочу, чтобы это было нечувствительным к регистру, как бы я к этому подошел?
Ответы
Ответ 1
Это довольно просто; вам просто нужно вызвать strtolower()
для обеих переменных.
Если вам нужно иметь дело с Unicode или международными наборами символов, вы можете использовать mb_strtolower()
.
Обратите внимание, что в других ответах предлагается использовать strcasecmp()
— эта функция не обрабатывает многобайтовые символы, поэтому результаты для любой строки UTF-8 будут фиктивными.
Ответ 2
strcasecmp()
возвращает 0, если строки одинаковы (кроме вариантов case), поэтому вы можете использовать:
if (strcasecmp($var1, $var2) == 0) {
}
Ответ 3
Если ваша строка находится в одной байтовой кодировке, она проста:
if(strtolower($var1) === strtolower($var2))
Если ваша строка UTF-8, вы должны учитывать сложность Unicode: от-нижнего и верхнего - не биективные функции, т.е. если у вас есть строчный символ, преобразуйте его в верхний регистр, и преобразовать его обратно в нижний регистр, вы можете не иметь ту же самую кодовую точку (и то же самое верно, если вы начинаете с символа верхнего регистра).
например.
- "İ" (
Latin Capital Letter I with Dot Above, U+0130
) является символом верхнего регистра, с "i" (Latin Small Letter I, U+0069
) в качестве варианта его нижнего регистра - и "i" вариант верхнего регистра - "I" (Latin Capital Letter I, U+0049
).
- "ı" (
Latin Small Letter Dotless I, U+0131
) является строчным символом с буквой "I" (Latin Capital Letter I, U+0049
) в качестве варианта с верхним регистром, а "нижний регистр" - "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)
- и если вы сравните их на уровне байта, это не вернет true!
Но в 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 пакет для Normalizer
- вам следует оптимизировать эту функцию, сначала проверив, насколько они равны ^^
- вы можете использовать NFC вместо NFKC, потому что NFKC удаляет слишком много различий в форматировании для вашего вкуса.
- вам нужно решить для себя, если вам действительно нужна вся эта сложность или вы предпочитаете более простой вариант этой функции.
Ответ 4
if(strtolower($var1) == strtolower($var2)){
}
Ответ 5
Используйте strcasecmp.
Ответ 6
Почему бы и нет:
if(strtolower($var1) == strtolower($var2)){
}