Есть ли способ сравнить две строки на испанском, независимо от акцентов в PHP?

Мой вопрос, учитывая, что у меня есть следующий PHP-код для сравнения двух строк:

   $cadena1='JUAN LÓPEZ YÁÑEZ';
$cadena2='JUAN LOPEZ YÁÑEZ';

if($cadena1===$cadena2){
echo '<p style="color: green;">The strings match!</p>';
}else{
echo '<p style="color: red;">The strings do not match. Accent sensitive?</p>';
}

Я замечаю, например, что если я сравниваю ЛОПЕЗ а также LÓPEZ тогда сравнение становится ложным.

Есть ли способ или функция для сравнения этих строк независимо от испанских акцентов?

2

Решение

Я бы заменил все акценты в ваших строках, прежде чем сравнивать их. Вы можете сделать это, используя следующий код:

$replacements = array('Ó'=>'O', 'Á'=>'A', 'Ñ' => 'N'); //Add the remaining Spanish accents.
$output = strtr("JUAN LÓPEZ YÁÑEZ",$replacements);

output теперь будет равен cadena2,

4

Другие решения

Две строки сравниваются с ложными, потому что они на самом деле отличаются последовательностью байтов. Чтобы сравнить их, нужно их нормализовать любым способом.

Лучший способ сделать это — использовать класс Transliterator, часть intl расширение на PHP 5.4+.

Тестовый код:

<?php
$transliterator = Transliterator::createFromRules(':: NFD; :: [:Nonspacing Mark:] Remove; :: NFC;', Transliterator::FORWARD);
$test = ['abcd', 'èe', '€', 'àòùìéëü', 'àòùìéëü', 'tiësto'];
foreach($test as $e) {
$normalized = $transliterator->transliterate($e);
echo $e. ' --> '.$normalized."\n";
}
?>

Результат:

abcd --> abcd
èe --> ee
€ --> €
àòùìéëü --> aouieeu
àòùìéëü --> aouieeu
tiësto --> tiesto

(взято из моего ответа здесь: mySQL — сопоставление латинской (английской) формы ввода с данными utf8 (не английскими) )

Это заменяет символы в соответствии с таблицами библиотеки ICU, которые чрезвычайно полны и хорошо протестированы. Перед транслитерацией это нормализует строку, поэтому она соответствует любому возможному способу представления символов, таких как — (например, может быть представлен 1 многобайтовым символом или как комбинация двух символов ˜ и n).

В отличие от использования soundex (), который также очень ресурсоемкий, он не сравнивает звуки, поэтому он более точный.

2

Почему бы просто не использовать сопоставления из расширения intl, класса Collator?

  • с начальным уровнем игнорировать акценты а также дело
  • с основным уровнем и установите для атрибута Collator :: CASE_LEVEL значение On, чтобы игнорировать акценты, но не регистр

(и так далее — см. подробности в документации ICU или PHP)

$cadena1 = 'JUAN LÓPEZ YÁÑEZ';
$cadena2 = 'JUAN LOPEZ YÁÑEZ';
$coll = new Collator('es_ES');
$coll->setStrength(Collator::PRIMARY);
//$coll->setAttribute(Collator::CASE_LEVEL, Collator::ON);
var_dump($coll->compare($cadena1, $cadena2)); // 0 = equals

(конечно, строки должны быть в кодировке UTF-8)

1

Вы можете попробовать soundex() функция, которая работает по крайней мере для вашего примера:

var_dump(soundex('LOPEZ'));
// string(4) "L120"
var_dump(soundex('LÓPEZ'));
// string(4) "L120"

Вы должны проверить это для разных слов, и если результаты не достаточно хороши, вы можете попробовать similar_text().

Увидеть пример с вашим кодом.

0

Попробуйте эту функцию из http://sourcecookbook.com/en/recipes/8/function-to-slugify-strings-in-php. Он заменит не-ASCII-символы на ASCII-символы в строке.

$cadena1='JUAN LÓPEZ YÁÑEZ';
$cadena2='JUAN LOPEZ YÁÑEZ';

function slugify( $text ) {

// replace non letter or digits by -
$text = preg_replace('~[^\\pL\d]+~u', '-', $text);
$text = trim($text, '-');

/**
* //IGNORE//TRANSLIT to avoid errors on non translatable characters and still translate other characters
* //TRANSLIT to out_charset transliteration is activated
* //IGNORE, characters that cannot be represented in the target charset are silently discarded
*/
$text = iconv('utf-8', 'ASCII//IGNORE//TRANSLIT', $text);
$text = strtolower(trim($text));

// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);

return empty($text) ? '' : $text;
}

var_dump( slugify( $cadena1 ) );    // string(16) "juan-lopez-yanez"var_dump( slugify( $cadena2 ) );    // string(16) "juan-lopez-yanez"
0