【问题标题】:Generate shorted unique username based on array of first names and last names根据名字和姓氏数组生成短的唯一用户名
【发布时间】:2011-05-09 06:14:17
【问题描述】:

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

$users = [
    ['first_name' => 'Bob', 'last_name' => 'Smith'],
    ['first_name' => 'Steve', 'last_name' => 'Little'],
    ['first_name' => 'Eric', 'last_name' => 'Fielder'],
    ['first_name' => 'Steve', 'last_name' => 'Richardson'],
    ['first_name' => 'Bob', 'last_name' => 'Sanders'],
    ['first_name' => 'Bob', 'last_name' => 'Sanders'],
    ['first_name' => 'Bob', 'last_name' => 'Smith'],
];

所需逻辑:

  • 如果没有重复的名字,则仅使用名字作为用户名 (“埃里克”)。

  • 如果有两个名字的姓氏首字母相同但首字母不同,它将使用名字作为姓氏首字母(“Steve L.”和“Steve R. ”)。

  • 如果多人拥有姓氏和姓氏首字母,则返回全名(“Bob Smith”和“Bob Sanders”)。

  • 最后,如果找到了相同的确切名称,那么它将在每个名称后面附加一个数字,如下所示:“Bob Sanders (1)”和“Bob Sanders (2) >"

我希望这可以有效地完成,而不是用很多循环,但我一辈子都想不通。

【问题讨论】:

    标签: php arrays multidimensional-array unique


    【解决方案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>');
        ?>
    

    【讨论】:

    • 只要确保名称已经事先清理干净:标准化大小写并删除多余的空格/字符。
    【解决方案2】:

    我发现 Nayru 的 sn-p 过于宽泛、难以理解并且在内存方面过于昂贵——它存储了冗余的计数以便于查找。值得称赞的是,它确实保持了行的顺序——如果这很重要的话。

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

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

    代码:(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',
      ),
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      相关资源
      最近更新 更多