问题
I am provided a list of names in upper case. For the purpose of a salutation in an email I would like them them to be Proper Cased.
Easy enough to do using PHP's ucwords. But I feel I need some regex function to handle common exceptions, such as:
"O'Hara", "McDonald", "van der Sloot", etc
It's not so much that I need help constructing a regex statement to handle the three examples above (tho that would be nice), as it is that I don't know what all the common exceptions might be.
Surely someone has faced this issue before, any pointers to published solutions or something you could share?
回答1:
Using regular expressions in a short provided list could be easy, but if you must handle hundreds or thousands of records it's very hard to be bullet proof.
I'd rather use something that can't affect someone else. How do you know if Mr. "MACDONALD" prefers "Macdonald"?
You're correcting someone else's error. If source cannot be corrected you could use something like this:
<?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.
)
*/
?>
I hope it be useful.
回答2:
I wrote this today to implement in an app I'm working on. I think this code is pretty self explanatory with comments. It's not 100% accurate in all cases but it will handle most of your western names easily.
Examples:
mary-jane => Mary-Jane
o'brien => O'Brien
Joël VON WINTEREGG => Joël von Winteregg
jose de la acosta => Jose de la Acosta
The code is extensible in that you may add any string value to the arrays at the top to suit your needs. Please study it and add any special feature that may be required.
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);
}
回答3:
I wrote a small lib for this: https://github.com/tamtamchik/namecase You can install it with Composer.
For your inputs it produces exactly what you need using the following code:
<?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;
}
Call function str_name_case
that is shipped with a lib on any name string, and it'll be converted to proper case. For your examples output will become:
O'HARA => O'Hara
MCDONALD => McDonald
VAN DER SLOOT => van der Sloot
来源:https://stackoverflow.com/questions/11529213/given-upper-case-names-transform-to-proper-case-handling-ohara-mcdonald