在PHP中拆分名字和姓氏的最佳方法

Sha*_*ock 14 php

我坚持使用NAME字段,通常采用以下格式:

FirstName LastName
Run Code Online (Sandbox Code Playgroud)

但是,我也偶尔会出现以下任何格式的名称(带前缀或后缀):

Mr. First Last
First Last Jr.
Run Code Online (Sandbox Code Playgroud)

人们认为在PHP中将这些变量分割为FIRST/LAST名称变量的安全方法是什么?我无法想出任何一直在工作的东西......

Fra*_*wis 22

正则表达式是处理这类事情的最佳方式.试试这件 - 它会拉出前缀,名字,姓氏和后缀:

$array = array(
    'FirstName LastName',
    'Mr. First Last',
    'First Last Jr.',
    'Shaqueal O’neal',
    'D’angelo Hall',
);

foreach ($array as $name)
{
    $results = array();
    echo $name;
    preg_match('#^(\w+\.)?\s*([\'\’\w]+)\s+([\'\’\w]+)\s*(\w+\.?)?$#', $name, $results);
print_r($results);
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

FirstName LastName
Array
(
    [0] => FirstName LastName
    [1] => 
    [2] => FirstName
    [3] => LastName
)
Mr. First Last
Array
(
    [0] => Mr. First Last
    [1] => Mr.
    [2] => First
    [3] => Last
)
First Last Jr.
Array
(
    [0] => First Last Jr.
    [1] => 
    [2] => First
    [3] => Last
    [4] => Jr.
)
shaqueal o’neal
Array
(
    [0] => shaqueal o’neal
    [1] => 
    [2] => shaqueal
    [3] => o’neal
)
d’angelo hall
Array
(
    [0] => d’angelo hall
    [1] => 
    [2] => d’angelo
    [3] => hall
)
Run Code Online (Sandbox Code Playgroud)

等等…

所以在数组中 $array[0]包含整个字符串.$array[2]始终是名字,$array[3]始终是姓氏. $array[1]是前缀,$array[4](并不总是设置)是后缀.我还添加了代码来处理像Shaqueal O'neal和D'angelo Hall这样的名字.


Sti*_*ing 17

接受的答案不适用于英语以外的语言或"Oscar de la Hoya"等名称.

这是我所做的一些我认为utf-8安全且适用于所有这些情况的东西,建立在接受的答案假设前缀和后缀将具有句点的基础上:

/**
 * splits single name string into salutation, first, last, suffix
 * 
 * @param string $name
 * @return array
 */
public static function doSplitName($name)
{
    $results = array();

    $r = explode(' ', $name);
    $size = count($r);

    //check first for period, assume salutation if so
    if (mb_strpos($r[0], '.') === false)
    {
        $results['salutation'] = '';
        $results['first'] = $r[0];
    }
    else
    {
        $results['salutation'] = $r[0];
        $results['first'] = $r[1];
    }

    //check last for period, assume suffix if so
    if (mb_strpos($r[$size - 1], '.') === false)
    {
        $results['suffix'] = '';
    }
    else
    {
        $results['suffix'] = $r[$size - 1];
    }

    //combine remains into last
    $start = ($results['salutation']) ? 2 : 1;
    $end = ($results['suffix']) ? $size - 2 : $size - 1;

    $last = '';
    for ($i = $start; $i <= $end; $i++)
    {
        $last .= ' '.$r[$i];
    }
    $results['last'] = trim($last);

    return $results;
}
Run Code Online (Sandbox Code Playgroud)

这是phpunit测试:

public function testDoSplitName()
{
    $array = array(
        'FirstName LastName',
        'Mr. First Last',
        'First Last Jr.',
        'Shaqueal O\'neal',
        'D’angelo Hall',
        'Václav Havel',
        'Oscar De La Hoya',
        '?????? ????????', //cyrillic
        '????? ????????', //yiddish
    );

    $assertions = array(
            array(
                    'salutation' => '',
                    'first' => 'FirstName',
                    'last' => 'LastName',
                    'suffix' => ''
                ),
            array(
                    'salutation' => 'Mr.',
                    'first' => 'First',
                    'last' => 'Last',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => 'First',
                    'last' => 'Last',
                    'suffix' => 'Jr.'
                ),
            array(
                    'salutation' => '',
                    'first' => 'Shaqueal',
                    'last' => 'O\'neal',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => 'D’angelo',
                    'last' => 'Hall',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => 'Václav',
                    'last' => 'Havel',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => 'Oscar',
                    'last' => 'De La Hoya',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => '??????',
                    'last' => '????????',
                    'suffix' => ''
                ),
            array(
                    'salutation' => '',
                    'first' => '?????',
                    'last' => '????????',
                    'suffix' => ''
                ),
        );

    foreach ($array as $key => $name)
    {
        $result = Customer::doSplitName($name);

        $this->assertEquals($assertions[$key], $result);
    }
}
Run Code Online (Sandbox Code Playgroud)


mar*_*kli 5

你找不到一种安全的方法来解决这个问题,即使是人类总能分辨哪些部分属于名字,哪些部分属于姓氏,特别是当其中一个部分包含几个单词时:Andrea Frank Gutenberg.中间部分弗兰克可以是第二个名字或姓氏为古腾堡的姓氏.

您可以做的最好的事情是,为firstname和lastname提供不同的输入字段,并在数据库中将它们分开安全,这样就可以避免很多问题.

  • 作为一个学究,假设人们的名字有两个部分,但情况并非总是如此。http://www.kalzumeus.com/2010/06/17/falsehoods-programmers- believe-about-names/ (2认同)