【问题标题】:Given upper case names transform to Proper Case, handling "O'Hara", "McDonald" "van der Sloot" etc给定大写名称转换为正确大小写,处理“O'Hara”、“McDonald”、“van der Sloot”等
【发布时间】:2012-07-16 18:29:54
【问题描述】:

为我提供了一个大写名称列表。为了在电子邮件中表达敬意,我希望它们是正确大小写的。

使用 PHP 的 ucwords 很容易做到。但是我觉得我需要一些正则表达式函数来处理常见的异常,例如:

“奥哈拉”、“麦当劳”、“范德斯洛特”等

与其说我需要帮助构建一个正则表达式语句来处理上面的三个示例(那会很好),不如说我不知道​​所有常见的异常可能是什么。

肯定有人以前遇到过这个问题,有任何指向已发布解决方案的指针或您可以分享的东西吗?

【问题讨论】:

标签: php regex text text-processing text-parsing


【解决方案1】:

在提供的简短列表中使用正则表达式可能很容易,但如果您必须处理数百或数千条记录,则很难做到无懈可击。

我宁愿使用不会影响其他人的东西。你怎么知道“麦克唐纳”先生是否喜欢“麦克唐纳”?

你在纠正别人的错误。如果源无法更正,您可以使用以下内容:

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

希望对你有用。

【讨论】:

  • 我一直在考虑这个问题,并认为你的方法是一个有趣的方法的一部分。如果 $corrected_names 数组按如下方式生成会怎样:提取我们可以找到的每个名称(例如从电话簿或人口普查中),其中名称的大小写模式不止一种,只保留最流行的。这样,每个名称都会以该名称最常见的模式使用大写进行“更正”。完美的?当然不是;但我尽量不让完美成为善的敌人。
  • 我正在考虑这件事,我将采取的方式可能会激励客户/客户/营销部门审查个人信息(如果可能,使用电子邮件表格或电话);提供,可能是一种奖励,如折扣/礼物。
【解决方案2】:

我今天写这个是为了在我正在开发的应用程序中实现。我认为这段代码对于 cmets 来说是非常自我解释的。它并非在所有情况下都 100% 准确,但它可以轻松处理您的大部分西方名字。

例子:

mary-jane =&gt; Mary-Jane

o'brien =&gt; O'Brien

Joël VON WINTEREGG =&gt; Joël von Winteregg

jose de la acosta =&gt; 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);
}

【讨论】:

    【解决方案3】:

    我为此写了一个小库: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,它会被转换为正确的大小写。对于您的示例输出将变为:

    奥哈拉 => 奥哈拉
    麦当劳 => 麦当劳
    范德斯洛特 => 范德斯洛特

    【讨论】:

    • 是的 - 现在这是一个更好的答案,感谢您的建议。您的图书馆会如何处理像 "MACDONALD" 这样的名称,它有两种大写形式?
    • @Mogsdad 默认情况下它会转换为MacDonald 但如果有功能请求,我可能会为此添加一个选项。我正在尝试坚持使用原始 Perl 版本 metacpan.org/pod/distribution/Lingua-EN-NameCase/README,MacDonald 也不例外。
    猜你喜欢
    • 2017-08-17
    • 2022-08-16
    • 2018-12-18
    • 2019-05-15
    • 2015-11-28
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多