首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >大写姓,不包括姓氏的小写前缀部分

大写姓,不包括姓氏的小写前缀部分
EN

Stack Overflow用户
提问于 2017-01-20 15:22:22
回答 6查看 1.5K关注 0票数 14

我正在尝试确定一个大写姓的方法,但是,不包括小写前缀。

名称及其转换的例子:

  • MacArthur -> MacARTHUR
  • McDavid -> McDAVID
  • LeBlanc -> LeBLANC
  • McIntyre -> McINTYRE
  • de Wit -> de WIT

还有一些名称将包含需要完全大写的姓氏,因此一个识别前缀(如strchr())的简单函数是不够的:

  • Macmaster -> MACMASTER
  • 麦金托什->麦金塔

mb_strtoupper()函数是不合适的,因为它大写了整个字符串。类似地,strtoupper()是不合适的,并且在重音名称上也会失去重音。

有一些答案可以部分回答这个问题,例如:使用PHP的大写,但是,常见的缺陷是假设所有姓为Mac的名字后面都跟着一个大写字母。

名称在数据库中被正确大写,因此我们可以假设拼写为Macarthur的名称是正确的,或者MacArthur对于其他人是正确的。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-01-20 15:54:25

按照规则,在上一封大写字母之后,所有东西都要资本化。

代码语言:javascript
复制
preg_replace_callback('/\p{Lu}\p{Ll}+$/u', 
                      function ($m) { return mb_strtoupper($m[0]); },
                      $name)

\p{Lu}\p{Ll}分别是Unicode大写字符和小写字符,mb_strtoupper是unicode感知的…。对于一个仅适用于ASCII的简单变体,也可以这样做:

代码语言:javascript
复制
preg_replace_callback('/[A-Z][a-z]+$/', 
                      function ($m) { return strtoupper($m[0]); },
                      $name)
票数 8
EN

Stack Overflow用户

发布于 2017-10-23 20:47:37

下面是一个基本的算法,它可以避免神秘的正则表达式:

  1. 为文字姓氏创建一个多字节安全字符数组(因为它存在于数据库中)。
  2. 以多字节安全大写形式创建第二个字符数组。
  3. 交叉两个数组以确定最终大写字符的索引。
  4. 通过索引将文字姓氏与大写形式连接在索引之后。

以代码形式:

代码语言:javascript
复制
<?php
$names = [
    'MacArthur',
    'McDavid',
    'LeBlanc',
    'McIntyre',
    'de Wit',
    'Macmaster',
    'Macintosh',
    'MacMac',
    'die Über',
    'Van der Beek',
    'johnson',
    'Lindström',
    'Cehlárik',
];

// Uppercase after the last capital letter
function normalizeSurname($name) {
    // Split surname into a Unicode character array
    $chars = preg_split('//u', $name, -1, PREG_SPLIT_NO_EMPTY);

    // Capitalize surname and split into a character array
    $name_upper = mb_convert_case($name, MB_CASE_UPPER);
    $chars_upper = preg_split('//u', $name_upper, -1, PREG_SPLIT_NO_EMPTY);

    // Find the index of the last capitalize letter
    @$last_capital_idx = array_slice(array_keys(array_intersect($chars, $chars_upper)), -1)[0] ?: 0;

    // Concatenate the literal surname up to the index, and capitalized surname thereafter
    return mb_substr($name, 0, $last_capital_idx) . mb_substr($name_upper, $last_capital_idx);
}

// Loop through the surnames and display in normalized form
foreach($names as $name) {
    echo sprintf("%s -> %s\n", 
        $name,
        normalizeSurname($name)
    );
}

您将得到如下输出:

代码语言:javascript
复制
MacArthur -> MacARTHUR
McDavid -> McDAVID
LeBlanc -> LeBLANC
McIntyre -> McINTYRE
de Wit -> de WIT
Macmaster -> MACMASTER
Macintosh -> MACINTOSH
MacMac -> MacMAC
die Über -> die ÜBER
Van der Beek -> Van der BEEK
johnson -> JOHNSON
Lindström -> LINDSTRÖM
Cehlárik -> CEHLÁRIK

这就产生了这样的假设:一个完全小写的姓氏应该大写。改变这种行为是很容易的。

票数 3
EN

Stack Overflow用户

发布于 2017-01-20 15:44:08

我相信这是解决问题的办法:

代码语言:javascript
复制
$names = array(
    'MacArthur',
    'Macarthur',
    'ÜtaTest',
    'de Wit'
);

$pattern = '~(?<prefix>(?:\p{Lu}.+|.+\s+))(?<suffix>\p{Lu}.*)~';
foreach ($names as $key => $name) {
    if (preg_match($pattern, $name, $matches)) {
        $names[$key] = $matches['prefix'] . mb_strtoupper($matches['suffix']);
    } else {
        $names[$key] = mb_strtoupper($name);
    }
}

print_r($names);

它为上面的输入数组产生以下结果:

代码语言:javascript
复制
Array
(
    [0] => MacARTHUR
    [1] => MACARTHUR
    [2] => ÜtaTEST
    [3] => de WIT
)

正则表达式的简要说明:

代码语言:javascript
复制
(?<prefix>             # name of the captured group
   (?:                 # ignore this group
       \p{Lu}.+        # any uppercase character followed by any character
       |               # OR
       .+\s+           # any character followed by white space
   )
)
(?<suffix>             # name of the captured group
    \p{Lu}.*           # any uppercase character followed by any character
)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41767011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档