【问题标题】:Formatting Human Names - PHP (or any language) library?格式化人名 - PHP(或任何语言)库?
【发布时间】:2013-03-31 02:41:10
【问题描述】:

有没有办法格式化人名?例如,“joHn doe”应该是“John Doe”。或者“angus macgyver”应该是“Angus MacGyver”。等等

我知道任何解决方案都可能不完整(命名规则太多),但有总比没有好。有什么建议吗?

【问题讨论】:

  • 您要添加一个大写字母,其余的小写?
  • ucfirst 和一个词缀列表会有很长的路要走。众所周知的 20% 的努力。
  • 别打扰了。要么完全按照用户输入的方式保留它,要么通过简单的ucfirst() 运行它。
  • 在 Python 中:x = 'joHn dOE'; x.title() 返回 'John Doe'
  • @DarylGill 标题写着“任何语言”。

标签: php formatting string-formatting


【解决方案1】:

正如 cmets 中已经建议的那样,在 PHP 中,您可以执行以下操作:

$name_formatted = ucfirst(strtolower($name_unformatted));

这将处理您 90% 的案件。然后我会将其放入一个函数中并添加规则来处理 MacGuyver、O'Reilly 类型的异常。

更新: 正如所指出的,ucfirst 只处理字符串中的第一个单词。您可以使用正则表达式将每个单词中的所有首字母大写,或者执行如下函数:

<?php
$name_unformatted = "JOHN DOE";

function format_name($name_unformatted)
{
   $name_formatted = ucwords(strtolower($name_unformatted));  // this will handle 90% of the names

   // ucwords will work for most strings, but if you wanted to break out each word so you can deal with exceptions, you could do something like this:
   $separator = array(" ","-","+","'");
   foreach($separator as $s)
   {
      if (strpos($name_formatted, $s) !== false)
      {
         $word = explode($s, $name_formatted);
         $tmp_ary = array_map("ucfirst", array_map("strtolower", $word));  // whatever processing you want to do here
         $name_formatted = implode($s, $tmp_ary);
      }
   }

   return $name_formatted;
}

echo format_name($name_unformatted);
?>

你可以扩展这个函数来处理你的名字异常。

【讨论】:

  • ucfirst 不会为 JOHN DOE 做任何事情。
  • 好吧,是的,也不是@snoopy76 - 我的代码将整个字符串小写,然后将第一个字母大写。我将使用一个可以处理所有单词的函数来更新我的答案。
  • 卫生署!忘记了 PHP 中的 ucwords 函数。
  • 我看到了你的功能的优点。尽管我意识到它无法处理名称的所有可能情况(因为规则只是指数级的),但我认为这已经是一个很好的开始。我很好奇您用作单词分隔符的+ 符号。您有使用+ 的名称示例吗?
  • 我认为我从 php 网站获取了该代码的 sn-p - 您可以删除 + 因为它可能未在您的场景中使用。如果你觉得有用,请接受我的回答。谢谢!
【解决方案2】:

我正在寻找一个可以处理名称正确大写的 php 脚本。虽然我意识到很难处理 100% 的案件

https://en.wikipedia.org/wiki/List_of_family_name_affixes

我认为这个脚本可以很好地处理 95% 的用例,至少对我们来说是这样。这当然是一个很好的起点。

http://www.media-division.com/correct-name-capitalization-in-php/

function titleCase($string) 
{
    $word_splitters = array(' ', '-', "O'", "L'", "D'", 'St.', 'Mc');
    $lowercase_exceptions = array('the', 'van', 'den', 'von', 'und', 'der', 'de', 'da', 'of', 'and', "l'", "d'");
    $uppercase_exceptions = array('III', 'IV', 'VI', 'VII', 'VIII', 'IX');

    $string = strtolower($string);
    foreach ($word_splitters as $delimiter)
    { 
        $words = explode($delimiter, $string); 
        $newwords = array(); 
        foreach ($words as $word)
        { 
            if (in_array(strtoupper($word), $uppercase_exceptions))
                $word = strtoupper($word);
            else
            if (!in_array($word, $lowercase_exceptions))
                $word = ucfirst($word); 

            $newwords[] = $word;
        }

        if (in_array(strtolower($delimiter), $lowercase_exceptions))
            $delimiter = strtolower($delimiter);

        $string = join($delimiter, $newwords); 
    } 
    return $string; 
}

【讨论】:

    【解决方案3】:

    对于意大利名字的问题,我找到了一个简单的解决方案

    function formatName(string $firstName, string $lastName): array
    {
        $delimiters = " -’'\t\r\n\f\v";
    
        return \array_map(
            fn ($string) => \ucwords(\mb_strtolower($string), $delimiters),
            [$firstName, $lastName]
        );
    }
    

    在我的情况下,我必须处理像 D'AmicoDe AngelisDi CataldoRossi-Bianchi 这样的姓氏,这个快速的解决方案效果很好。

    主要玩家是

    \ucwords(\mb_strtolower($string), $delimiters)
    

    其余的只是我通过划分名字和姓氏来处理名字的一部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多