Сравнение строк без учета регистра - PullRequest
61 голосов
/ 29 марта 2011

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

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

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

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

Ответы [ 6 ]

100 голосов
/ 29 марта 2011

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

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

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

66 голосов
/ 29 марта 2011

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

if (strcasecmp($var1, $var2) == 0) {
}
14 голосов
/ 09 августа 2016

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

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» в нижнем регистре - «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 для нормализатора
  • . Вы должны оптимизировать эту функцию, сначала проверив, если ониВы просто равны ^^
  • вы можете использовать NFC вместо NFKC, потому что NFKC удаляет слишком много различий форматирования на ваш вкус
  • вы должны решить для себя, если вам действительно нужно всеэта сложность или если вы предпочитаете более простой вариант этой функции
1 голос
/ 29 марта 2011
if(strtolower($var1) == strtolower($var2)){
}
0 голосов
/ 29 марта 2011

Использование strcasecmp .

0 голосов
/ 29 марта 2011

Почему бы и нет:

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