从名字和姓氏字段中获取最短的唯一名称

时间:2011-05-09 06:14:17

标签: php arrays formatting username

我有一个名为users的多维数组,格式如下,我正在尝试创建一个脚本,根据这些信息创建一个“用户名”:

$users(first_name => 'Bob', last_name => 'Smith')
$users(first_name => 'Steve', last_name => 'Little')
$users(first_name => 'Eric', last_name => 'Fielder')
$users(first_name => 'Steve', last_name => 'Richardson')
$users(first_name => 'Bob', last_name => 'Sanders')
$users(first_name => 'Bob', last_name => 'Sanders')
  • 如果有的话 没有重复使用的名字 第一个名称作为用户名 ( “埃里克”)。

  • 如果有两个名称相同 首先但不同的首字母 在姓氏中它将使用 名字作为最后一个首字母(“史蒂夫 L。“和” Steve R。“)。

  • 如果有多人拥有最后一个 名字和最后一个首字母然后它 返回全名(“ Bob Smith ”和 “ Bob Sanders ”)。

  • 最后,如果SAME确切名称是 发现它会附加一个数字 每个人都这样:“鲍勃桑德斯(1)”和 “ Bob Sanders(2)

我希望这可以有效地完成,而不是通过很多循环,但我无法理解我的生活。

提前感谢您提供任何帮助!

2 个答案:

答案 0 :(得分:1)

这个脚本不是那么漂亮,但几乎可以做你想要的。请注意,它只使用两个循环,但需要一些额外的内存来存储有关用户的元数据:

    <?php

     $users = array(
             array("first_name"=>"Bob", "last_name"=>"Smith"),
             array("first_name"=>"Steve", "last_name"=>"Little"),
             array("first_name"=>"Eric", "last_name"=>"Fielder"),
             array("first_name"=>"Steve", "last_name"=>"Richardson"),
             array("first_name"=>"Bob", "last_name"=>"Sanders"),
             array("first_name"=>"Bob", "last_name"=>"Sanders")
             );

     $_users_info = array("first_name_count"=>array(),"last_name_count"=>array(),"first_name_last_initial_count"=>array());
     foreach($users as $user){
             $_users_info["first_name_count"][$user["first_name"]] = isset($_users_info["first_name_count"][$user["first_name"]]) ? ++$_users_info["first_name_count"][$user["first_name"]] : 1;
             $_users_info["last_name_count"][$user["last_name"]] = isset($_users_info["last_name_count"][$user["last_name"]]) ? ++$_users_info["last_name_count"][$user["last_name"]] : 1;
             $_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)] = isset($_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)]) ? ++$_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)] : 1;
             $_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]] = isset($_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]]) ? ++$_users_info["complete_name_count"][$user["first_name"]."#".$user["last_name"]] : 1;
             $_users_info["complete_name_allocated"][$user["first_name"]."#".$user["last_name"]] = 0;
     }

     print('<pre>');
     foreach($users as $user) {
             $username = null;
             if($_users_info["first_name_count"][$user["first_name"]]==1) $username = $user["first_name"];
             else if($_users_info["first_name_last_initial_count"][$user["first_name"]."#".substr($user["last_name"],0,1)]==1) $username = $user["first_name"]." ".substr($user["last_name"],0,1).".";
             else if($_users_info["last_name_count"][$user["last_name"]]==1) $username = $user["first_name"]." ".$user["last_name"];
             else $username = $user["first_name"]." ".$user["last_name"].sprintf(" (%d)",++$_users_info["complete_name_allocated"][$user["first_name"]."#".$user["last_name"]]);
             printf("%s %s => %s\n",$user["first_name"],$user["last_name"],$username);
     }
     print('</pre>');
    ?>

答案 1 :(得分:0)

我发现 Nayru 的代码段过于宽泛、难以理解,而且在内存方面太昂贵——它为了便于查找而存储了冗余的记录。值得称赞的是,它确实维护了行的顺序——如果这很重要的话。

另一种技术是将输入数据合并到嵌套组中(具有唯一级别/键),然后迭代这些合并级别并使用一组条件来生成所需的用户名。这可能是跟踪名称冲突的最紧凑的方法。我当然觉得这是一段更容易维护和阅读的代码。

*如果您的姓氏可能以多字节字符开头,则应使用 mb_substr() 来隔离第一个字母
*此代码段的结果不尊重输入的原始顺序,但如有必要,可以为此目的对其进行重构。
*它确实使用了几个循环,但这只是迭代嵌套级别的最有效方法——不要回避。

代码:(Demo)

foreach ($users as $row) {
    $grouped[$row['first_name']][$row['last_name'][0] ?? ''][$row['last_name']][] = $row;
}

$result = [];
foreach ($grouped as $firstName => $leadingLetterGroup) {
    $leadingLetterCount = count($leadingLetterGroup);
    foreach ($leadingLetterGroup as $leadingLetter => $lastNameGroup) {
        $lastNameCount = count($lastNameGroup);
        foreach ($lastNameGroup as $lastName => $rows) {
            if (count($rows) === 1) {
                if ($leadingLetterCount === 1) {
                    $username = $firstName;
                } elseif ($lastNameCount === 1) {
                    $username = "$firstName $leadingLetter.";
                } else {
                    $username = "$firstName $lastName";
                }
                $result[] = $rows[0] + ['username' => $username];
            } else {
                foreach ($rows as $i => $row) {
                    $username = sprintf("%s %s (%d)", $firstName, $lastName, $i + 1);
                    $result[] = $row + ['username' => $username];
                }
            }
        }
    }
}
var_export($result);

输出:

array (
  0 => 
  array (
    'first_name' => 'Bob',
    'last_name' => 'Smith',
    'username' => 'Bob Smith (1)',
  ),
  1 => 
  array (
    'first_name' => 'Bob',
    'last_name' => 'Smith',
    'username' => 'Bob Smith (2)',
  ),
  2 => 
  array (
    'first_name' => 'Bob',
    'last_name' => 'Sanders',
    'username' => 'Bob Sanders (1)',
  ),
  3 => 
  array (
    'first_name' => 'Bob',
    'last_name' => 'Sanders',
    'username' => 'Bob Sanders (2)',
  ),
  4 => 
  array (
    'first_name' => 'Steve',
    'last_name' => 'Little',
    'username' => 'Steve L.',
  ),
  5 => 
  array (
    'first_name' => 'Steve',
    'last_name' => 'Richardson',
    'username' => 'Steve R.',
  ),
  6 => 
  array (
    'first_name' => 'Eric',
    'last_name' => 'Fielder',
    'username' => 'Eric',
  ),
)