Если имена верхних регистров преобразуются в правильное дело, обрабатываются «О'Хара», «Макдональд», «Ван дер Слоут» и т. Д.

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

Достаточно легко сделать, используя PHP- ucwords . Но я чувствую, что мне нужна функция регулярных выражений для обработки общих исключений, таких как:

«О'Хара», «Макдональд», «Ван дер Слоут» и т. Д.

Дело не в том, что мне нужна помощь в создании выражения regex для обработки трех приведенных выше примеров (это было бы хорошо), поскольку я не знаю, каковы могут быть все общие исключения.

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

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

Я бы предпочел использовать то, что не может повлиять на кого-то другого. Откуда вы знаете, предпочитает ли «MACDONALD» «Макдональд»?

Вы исправляете чужую ошибку. Если источник не может быть исправлен, вы можете использовать что-то вроде этого:

<?php $provided_names = array( "SMITH", "O'HARA", "MCDONALD", "JONES", "VAN DER SLOOT", "MACDONALD" ); $corrected_names = array( "O'HARA" => "O'Hara", "MCDONALD" => "McDonald", "VAN DER SLOOT" => "van der Sloot" ); $email_text = array(); foreach ($provided_names as $provided_name) { $provided_name = !array_key_exists($provided_name, $corrected_names) ? ucwords(strtolower($provided_name)) : $corrected_names[$provided_name]; $email_text[] = "{$provided_name}, your message text."; } print_r($email_text); /* output: Array ( [0] => Smith, your message text. [1] => O'Hara, your message text. [2] => McDonald, your message text. [3] => Jones, your message text. [4] => van der Sloot, your message text. [5] => Macdonald, your message text. ) */ ?> 

Надеюсь, это будет полезно.

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

Примеры:

mary-jane => Mary-Jane

o'brien => O'Brien

Joël VON WINTEREGG => Joël von Winteregg

jose de la acosta => Jose de la Acosta

Код расширяется тем, что вы можете добавить любое строковое значение в массивы вверху в соответствии с вашими потребностями. Изучите его и добавьте любую специальную функцию, которая может потребоваться.

 function name_title_case($str) { // name parts that should be lowercase in most cases $ok_to_be_lower = array('av','af','da','dal','de','del','der','di','la','le','van','der','den','vel','von'); // name parts that should be lower even if at the beginning of a name $always_lower = array('van', 'der'); // Create an array from the parts of the string passed in $parts = explode(" ", mb_strtolower($str)); foreach ($parts as $part) { (in_array($part, $ok_to_be_lower)) ? $rules[$part] = 'nocaps' : $rules[$part] = 'caps'; } // Determine the first part in the string reset($rules); $first_part = key($rules); // Loop through and cap-or-dont-cap foreach ($rules as $part => $rule) { if ($rule == 'caps') { // ucfirst() words and also takes into account apostrophes and hyphens like this: // O'brien -> O'Brien || mary-kaye -> Mary-Kaye $part = str_replace('- ','-',ucwords(str_replace('-','- ', $part))); $c13n[] = str_replace('\' ', '\'', ucwords(str_replace('\'', '\' ', $part))); } else if ($part == $first_part && !in_array($part, $always_lower)) { // If the first part of the string is ok_to_be_lower, cap it anyway $c13n[] = ucfirst($part); } else { $c13n[] = $part; } } $titleized = implode(' ', $c13n); return trim($titleized); } 

Я написал для этого небольшую библиотеку: https://github.com/tamtamchik/namecase. Вы можете установить ее с помощью Composer .

Для ваших вводов он производит именно то, что вам нужно, используя следующий код:

 <?php require_once 'vendor/autoload.php'; // Composer autoload $arr = ["O'HARA", "MCDONALD", "VAN DER SLOOT"]; foreach ($arr as $name) { echo $name . ' => ' . str_name_case($name) . PHP_EOL; } 

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

О'ХАРА => О'Хара
MCDONALD => Макдональд
VAN DER SLOOT => ван дер Слоут