2012-07-17 23 views
5

Se me proporciona una lista de nombres en mayúsculas. A los efectos de un saludo en un correo electrónico, me gustaría que estén en buen estado.Nombres de mayúsculas dado se transforman a Caso adecuado, manejo de "O'Hara", "McDonald", "van der Sloot", etc.

Lo suficientemente fácil de hacer con PHP ucwords. Pero siento que necesito alguna función de expresiones regulares para manejar excepciones comunes, tales como:

"O'Hara", "McDonald", "van der Sloot", etc

No es tanto que Necesito ayuda para construir una declaración de expresiones regulares para manejar los tres ejemplos anteriores (aunque eso sería bueno), ya que es que no sé cuáles podrían ser todas las excepciones comunes.

Seguramente alguien se ha enfrentado a este problema antes, ¿algún indicador de soluciones publicadas o algo que podría compartir?

+1

lo tanto, usted no necesita ayuda con el código ... solo una lista de nombres? – vcsjones

+3

Esto es bastante difícil ya que MacDonald y Macdonald son deletreos correctos de un apellido y depende de la persona sobre cómo lo defienden. –

+3

¿Por qué no hacer que el usuario ingrese su propio nombre? –

Respuesta

2

Usar expresiones regulares en una breve lista proporcionada podría ser fácil, pero si debe manejar cientos o miles de registros, es muy difícil que sea a prueba de balas.

Prefiero usar algo que no puede afectar a otra persona. ¿Cómo se sabe si el Sr. "MACDONALD" prefiere "Macdonald"?

Estás corrigiendo el error de otra persona. Si la fuente no se puede corregir, podría usar algo como esto:

<?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. 
) 
*/ 
?> 

Espero que sea útil.

+1

He estado pensando en esto un poco más y creo que el suyo es parte de un enfoque interesante. ¿Qué sucede si la matriz $ corrected_names se generó de la siguiente manera: extraemos todos los nombres que podamos encontrar (por ejemplo, desde una guía telefónica o el censo), donde hay más de un patrón de capitalización para el nombre que retenga solo los más populares. De esta forma, cada nombre se "corregirá" con mayúsculas en el patrón más común para ese nombre. ¿Perfecto? Ciertamente no; pero estoy tratando de no dejar que lo perfecto sea enemigo del bien. – AllInOne

+0

Estaba pensando en ello y la forma en que lo haría podría ser motivador (utilizando un formulario de correo electrónico o una llamada telefónica, si es posible) para que el cliente/cliente/departamento de marketing revise la información personal; ofreciendo, puede ser, un tipo de premio como un descuento/regalo. – quantme

2

Escribí esto hoy para implementar en una aplicación en la que estoy trabajando. Creo que este código es bastante auto explicativo con comentarios. No es 100% exacto en todos los casos, pero manejará la mayoría de tus nombres occidentales fácilmente.

Ejemplos:

mary-jane => Mary-Jane

o'brien => O'Brien

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

jose de la acosta => Jose de la Acosta

El código es extensible en que usted puede añadir cualquier valor de cadena a las matrices en la parte superior para adaptarse tus necesidades. Estudie y agregue cualquier característica especial que pueda ser necesaria.

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); 
} 
2

escribí un pequeño lib para esto: https://github.com/tamtamchik/namecase puede instalarlo con Composer.

Para sus entradas se produce exactamente lo que necesita, usando el siguiente código:

<?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; 
} 

función Llamada str_name_case que se entrega con una librería en cualquier cadena de nombre, y va a ser convertida en caso apropiado.Para sus ejemplos salida será:

O'HARA => O'Hara
MCDONALD => McDonald
Van der Sloot => van der Sloot

+0

Sí, esa es una respuesta mucho mejor ahora, gracias por seguir el consejo. ¿Qué haría su biblioteca con un nombre como ["MACDONALD"] (https://en.wikipedia.org/wiki/Macdonald), que tiene dos formas de capitalización? – Mogsdad

+1

@Mogsdad por defecto se convertirá en 'MacDonald', pero podría agregar una opción para esto si hubiera una solicitud de función. Intento mantener la versión original de Perl https://metacpan.org/pod/distribution/Lingua-EN-NameCase/README y MacDonald no es una excepción. –

Cuestiones relacionadas