大写姓氏,包括 mccall => McCall 等例外情况

Posted

技术标签:

【中文标题】大写姓氏,包括 mccall => McCall 等例外情况【英文标题】:Capitalize last names including exceptions like mccall => McCall 【发布时间】:2012-03-22 01:13:12 【问题描述】:

我在使用 php 的名称大写时遇到问题。有些名称中有 2 个大写字母(例如:McCall)。在存储注册我们网站的用户名时,我们运行以下代码:

$name = ucwords(strtolower(trim($_SESSION['last_name']))) ;

这样做是将“mccall”更改为“Mccall”。我们需要一种方法来检查前 2 个字母是否以“Mc”开头,如果是,则将第三个字母大写,并将名称更改为“McCall”。

【问题讨论】:

让用户指定自己的名字而不做更改怎么样?我的姓是奥哈拉。有些人的姓是奥哈拉。你将无法区分。 Mac-而不是Mc-名称怎么样?包含连字符的姓氏? 我不久前遇到了同样的问题,并决定只允许用户指定他们自己的名称大小写,这既是出于@minitech 给出的原因,也是一个事实,如果用户想要, 他们可以有一个全大写的名字。 @three3,谁来决定一个名字的正确表示,而不是它所属的人? @three3:这对你的用户来说似乎有点傲慢。 如果您只想抓住懒惰的打字员,那么我会检查名称是全小写还是全大写,然后进行转换。如果有人写“mccall”或“MCCALL”,那么他们应该得到你的“更正”造成的任何错误。 (确保您的网站看起来没有被文盲儿童使用并没有错。) 【参考方案1】:

这是一个只是抓住 Mc 的解决方案,如果这就是你真正感兴趣的全部:

function capitalizeLastName($name) 
    $result = ucwords(strtolower(trim($_SESSION['last_name'])));

    if(substr($result, 0, 2) === 'Mc') 
        $result[2] = strtoupper($result[2]); // Yes, this works in PHP!
    

    return $result;

【讨论】:

致the anonymous editor:不,不会,如the first example of the documentation for ucwords所示。【参考方案2】:
$name = 'mccall';
$name = ucwords(strtolower(trim($name))) ;

if (strpos($name, 'Mc') === 0) 
    $name = 'Mc' . ucwords(substr($name, 2, strlen($name)));

echo $name; // McCall

【讨论】:

【参考方案3】:

仅供参考,我有一个非常好的函数,可以用于大写名称之外的更多内容。它还包含标题、短语等...

它需要一个字符串参数和一个布尔值。如果您要大写名称,则布尔值是 TRUE,如果是标题、短语等,则为 FALSE 或什么都没有......

使用很简单:

capitalize('mccall', TRUE); // result 'McCall'
capitalize('merry christmas and happy holidays!'); // result 'Merry Christmas and Happy Holidays!'
capitalize('jd mckinstry', TRUE); // result 'JD McKinstry'

功能

function capitalize($str, $is_name=FALSE) 
    $str = trim(stripcslashes($str));

    // exceptions to standard case conversion
    if ($is_name) 
        $all_uppercase = '';//'Aj|Jd';
        $all_lowercase = 'De La|De Las|Der|Van De|Van Der|Vit De|Von|Or|And|Van ';
    
    else   // addresses, essay titles ... and anything else
        $all_uppercase = 'Po|Rr|Se|Sw|Ne|Nw';
        $all_lowercase = 'A|And|As|By|In|Of|Or|To';
    

    $prefixes = 'Mc';
    $suffixes = "'S";

    // captialize all first letters
    $str = preg_replace('/\\b(\\w)/e', 'strtoupper("$1")', strtolower(trim($str)));

    if ($all_uppercase)    // capitalize acronymns and initialisms e.g. PHP
        $str = preg_replace("/\\b($all_uppercase)\\b/e", 'strtoupper("$1")', $str);
    

    if ($is_name) 
        if (strpos($str, " ") !== FALSE) 
            $ara = explode(" ", $str);
            foreach ($ara as $k => $v) 
                if ($k != count($ara)-1 && !preg_match("/[aeiouyAEIOUY]/", $v)) $ara[$k] = strtoupper($v);
            
            $str = implode(" ", $ara);
        
        elseif (!preg_match("/[aeiouy]/", $str)) 
            $str = strtoupper($str);
        
    

    if ($all_lowercase)    // decapitalize short words e.g. and
        if ($is_name)  // all occurences will be changed to lowercase
            $str = preg_replace("/\\b($all_lowercase)\\b/e", 'strtolower("$1")', $str);
        
        else   // first and last word will not be changed to lower case (i.e. titles)
            $str = preg_replace("/(?<=\\W)($all_lowercase)(?=\\W)/e", 'strtolower("$1")', $str);
        
    

    if ($prefixes)     // capitalize letter after certain name prefixes e.g 'Mc'
        $str = preg_replace("/\\b($prefixes)(\\w)/e", '"$1".strtoupper("$2")', $str);
    

    if ($suffixes)     // decapitalize certain word suffixes e.g. 's
        $str = preg_replace("/(\\w)($suffixes)\\b/e", '"$1".strtolower("$2")', $str);
    

    //  Mac Exceptions
    if (strpos($str, "Macd") === FALSE || strpos($str, "Macv") === FALSE) 
        $str = preg_replace("/Macd/", 'MacD', $str);
        $str = preg_replace("/Macv/", 'MacV', $str);
    

    return trim(stripcslashes($str));

正如你们中的一些人可能注意到的那样,这最初取自 PHP 网站,但我已经对其进行了培育并使其成熟为一种更有用和“智能”的方法!

【讨论】:

preg_replace 已弃用!已弃用:preg_replace():/e 修饰符已弃用,请改用 preg_replace_callback!更新您的代码。【参考方案4】:

我在搜索 PHP 手册中的函数时找到了这个答案,如 SpYk3HH 所回答。

preg_replace 已被弃用,正如 Michelangelo 正确注意到的那样。为了节省其他人一些时间在这里更新的功能。

加上一些支持荷兰名字的附加功能:

<?php

function capitalize($str, $is_name = FALSE) 

  $mylist = "S|‘s|‘t|A|Aan|Aan ‘t|Aan De|Aan Den|Aan Der|Aan Het|Aan T|Af|Al|Am|"
      . "Am De|Auf|Auf Dem|Auf Den|Auf Der|Auf Ter|Aus|Aus ‘m|Aus Dem|Aus Den|"
      . "Aus Der|Aus M|Ben|Bij|Bij ‘t|Bij De|Bij Den|Bij Het|Bij T|Bin|Boven D|"
      . "Boven D’|D|D’|Da|Dal|Dal’|Dalla|Das|De|De Die|De Die Le|De L|De L’|"
      . "De La|De Las|De Le|De Van Der|Deca|Degli|Dei|Del|Della|Den|Der|Des|"
      . "Di|Die Le|Do|Don|Dos|Du|El|Het|I|Im|In|In ‘t|In De|In Den|In Der|"
      . "In Het|In T|L|L’|La|Las|Le|Les|Lo|Los|Of|Onder|Onder ‘t|Onder De|"
      . "Onder Den|Onder Het|Onder T|Op|Op ‘t|Op De|Op Den|Op Der|Op Gen|Op Het|"
      . "Op T|Op Ten|Over|Over ‘t|Over De|Over Den|Over Het|Over T|S’|T|Te|Ten|"
      . "Ter|Tho|Thoe|Thor|To|Toe|Tot|Uijt|Uijt ‘t|Uijt De|Uijt Den|Uijt Te De|"
      . "Uijt Ten|Uit|Uit ‘t|Uit De|Uit Den|Uit Het|Uit T|Uit Te De|Uit Ten|"
      . "Unter|Van|Van ‘t|Van De|Van De L|Van De L’|Van Den|Van Der|Van Gen|"
      . "Van Het|Van La|Van T|Van Ter|Van Van De|Ver|Vom|Von|Von ‘t|Von Dem|"
      . "Von Den|Von Der|Von T|Voor|Voor ‘t|Voor De|Voor Den|Voor In ‘t|"
      . "Voor In T|Vor|Vor Der|Zu|Zum|Zur|Vit De|Or|And|Van|En";



  $str = trim($str);
  $str = stripcslashes($str);

  // exceptions to standard case conversion
  if ($is_name) 
    $all_uppercase = ''; //'Aj|Jd';
    $all_lowercase = $mylist;
  
  else   // addresses, essay titles ... and anything else
    $all_uppercase = 'Po|Rr|Se|Sw|Ne|Nw';
    $all_lowercase = 'A|And|As|By|In|Of|Or|To';
  

  $prefixes = 'Mc';
  $suffixes = "'S";

  // captialize all first letters
  $str = preg_replace_callback('/\\b(\\w)/', function($m) 
    return strtoupper($m[1]);
  , strtolower(trim($str)));

  if ($all_uppercase)    // capitalize acronymns and initialisms e.g. PHP
    $str = preg_replace("/\\b($all_uppercase)\\b/", function($m) 
      return strtoupper($m[1]);
    , $str);
  

  if ($is_name) 
    if (strpos($str, " ") !== FALSE) 
      $ara = explode(" ", $str);
      foreach ($ara as $k => $v) 
        if ($k != count($ara) - 1 && !preg_match("/[aeiouyAEIOUY]/", $v))
          $ara[$k] = strtoupper($v);
      
      $str = implode(" ", $ara);
    
    elseif (!preg_match("/[aeiouy]/", $str)) 
      $str = strtoupper($str);
    
  

  if ($all_lowercase)    // decapitalize short words e.g. and
    if ($is_name)  // all occurences will be changed to lowercase
      $str = preg_replace_callback("/\\b($all_lowercase)\\b/", function($m) 
        return strtolower($m[1]);
      , $str);
    
    else   // first and last word will not be changed to lower case (i.e. titles)
      $str = preg_replace_callback("/(?<=\\W)($all_lowercase)(?=\\W)/", function($m) 
        return strtolower($m[1]);
      , $str);
    
  

  if ($prefixes)     // capitalize letter after certain name prefixes e.g 'Mc'
    $str = preg_replace_callback("/\\b($prefixes)(\\w)/", function($m) 
      return $m[1] . strtoupper($m[2]);
    
        , $str);
  

  if ($suffixes)     // decapitalize certain word suffixes e.g. 's
    $str = preg_replace_callback("/(\\w)($suffixes)\\b/", function($m) 
      return $m[1] . strtoupper($m[2]);
    , $str);
  

  //  Mac Exceptions
  if (strpos($str, "Macd") === FALSE || strpos($str, "Macv") === FALSE) 
    //$str = preg_replace_callback("/Macd/", 'MacD', $str);
    //$str = preg_replace_callback("/Macv/", 'MacV', $str);
  

  return trim(stripcslashes($str));


//Array containing names to test
$testnames = [
  'van der vaart',
  'van vollenhoven',
  "van 't zandt",
  'van het zand',
  'el hamdoie',
  'van der Rooi-van Velzen',
  'Zuidewijn - van rooien',
  'teggelen onder t boven',
  "guido op 't drooge",
  "friso van drooge",
  'Zuidewijn - van rooien',
  'teggelen onder t boven',
  'ZUID-HOLLAND',
  "'s hertogen-bosch",
  "De Rooi Van Zuidewijn",
  "van onder",
  "Van Der Wijk-Zeewuster",
  "de Vries-van der Leest",
  "Den Oudsten - van 't Veldt",
  "Hare Koninklijke Hoogheid Alexia Juliana Marcela Laurentien Prinses der Nederlanden, Prinses van Oranje-Nassau",
  "Hare Koninklijke Hoogheid Máxima, Prinses der Nederlanden, Prinses van Oranje-Nassau, Mevrouw van Amsberg",
  "van Lippe-Biesterfeld van Vollenhoven",
];

foreach ($testnames as $name) 

  //First convert name to uppercase to get rid of the correct caps
  $name = strtoupper($name);
  //Output the capitalized name
  echo $name;
  echo " = ";
  //See output of function
  echo capitalize($name, TRUE);
  //Set br tag to get the next test name on next line
  echo "<br />";

【讨论】:

van der Vaart 应该以大写 V 开头,除非提供了名字。对于比利时,其他规则也适用。 上面的正确函数只适用于荷兰人的名字,我用这个函数来转换姓氏。如果您在没有名字的情况下使用它,或者在姓氏中使用首字母缩写,那么它将是正确的。 但除此之外,荷兰名字的功能目前还不错

以上是关于大写姓氏,包括 mccall => McCall 等例外情况的主要内容,如果未能解决你的问题,请参考以下文章

McCall提出的软件质量特性都有哪些?

如何将电子邮件地址中名字和姓氏的第一个字母大写?

SQL大写函数[重复]

在 C++ 中使用 toupper 函数的问题

在iOS网页中强制大写?

改变 span 的显示顺序