Генерировать сокращенное уникальное имя пользователя на основе массива имен и фамилий

#php #arrays #multidimensional-array #unique

#php #массивы #многомерный массив #уникальное

Вопрос:

У меня есть многомерный массив под названием 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'],
];
  

Требуемая логика:

  • Если нет повторяющихся имен, в качестве имени пользователя используется только первое имя («Eric«).

  • Если есть два имени с одинаковым именем, но разными начальными буквами в фамилии, то в качестве последней инициализации будет использоваться имя («Стив Л.» и «Стив Р.«).

  • Если у нескольких человек есть последнее имя и инициал, то оно возвращает полное имя («Боб Смит» и «Боб Сандерс«).

  • Наконец, если найдено одно и то же точное имя, то к каждому из них будет добавлено число, подобное этому: «Боб Сандерс (1)» и «Боб Сандерс (2)«

Я надеюсь, что это можно сделать эффективно и без большого количества циклов, но я не могу понять это, хоть убей.

Ответ №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 => %sn",$user["first_name"],$user["last_name"],$username);
     }
     print('</pre>');
    ?>
  

Комментарии:

1. Просто убедитесь, что имена были очищены заранее: стандартизируйте регистр и удалите лишние пробелы / символы.

Ответ №2:

Я нахожу фрагмент Nayru чрезмерно широким, сложным для отслеживания и слишком дорогим с точки зрения памяти — он хранит избыточные подсчеты ради удобства поиска. К его чести, он поддерживает порядок строк — если это имеет значение.

Другой метод заключается в объединении входных данных во вложенные группы (с уникальными уровнями / ключами), затем повторять эти объединенные уровни и использовать набор условий для генерации желаемых имен пользователей. Это может быть наиболее компактным способом отслеживания коллизий имен. Я, конечно, чувствую, что это гораздо более простой фрагмент кода для поддержки и чтения.

* если ваши фамилии могут начинаться с многобайтового символа, то mb_substr() следует использовать для выделения первой буквы
* результат этого фрагмента не соответствует первоначальному порядку ввода, но при необходимости его можно переработать для этой цели.
* в нем используется несколько циклов, но это всего лишь наиболее эффективное средство для повторения вложенных уровней — от него не следует уклоняться.

Код: (демо)

 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',
  ),
)