генерировать уникальный идентификатор для групп значений массива

У меня есть массив asosiative, который содержит данные о командах и игроках.

Пример:

$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'='John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Peter'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Zigmund'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Parker'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'='Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'='Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'='Alexander'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'='Ivan')
);

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

Я просто проверил, не существует ли рекламный индекс цикла foreach, поспорим, что это на игрока, а не на команду.

Ожидаемый результат:

$arr = array(
array('teamID'=> '1','teamName' => 'USA', 'playerName='John'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Peter'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Zigmund'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Parker'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'='Jan'),
array('teamID'=> '1','teamName' => 'USA', 'playerName'='Hector'),
array('teamID'=> '2','teamName' => 'Germany', 'playerName'='Alexander'),
array('teamID'=> '3','teamName' => 'Slovakia', 'playerName'='Ivan')
);

Есть идеи, как это решить?

1

Решение

Это решит вашу проблему (как одно из многих возможных решений).
Здесь у нас есть массив, содержащий каждое имя команды в качестве ключа, и увеличенный числовой идентификатор для каждого вхождения нового имени команды. Затем мы проверяем, существует ли ключ, если он существует, мы повторно используем присвоенный ему идентификатор. Если он не существует, мы создаем его и добавляем идентификатор, а затем увеличиваем целое число.

$teams_with_ids = [];
$teamids = [];
$i=0;
foreach( $arr AS $team ){
if( array_key_exists($team['teamName'], $teamids) ){
$team['teamID'] = $teamids[$team['teamName']];
} else {
$teamids[$team['teamName']] = $i;
$team['teamID'] = $i;
$i++;
}
array_push($teams_with_ids, $team);
}

РЕДАКТИРОВАТЬ:

Как указано в комментарии, вышеупомянутое решение не учитывает существующие идентификаторы в некоторых командах. Это делает:

$teams_with_ids = [];
$teamids = [];
$existing_ids = array_filter((array_map(function($team){ if( !empty( $team['teamID'] ) ) return intval($team['teamID']); },$arr)));
$i=0;
foreach( $arr AS $team ){
if( array_key_exists($team['teamName'], $teamids) ){
$team['teamID'] = $teamids[$team['teamName']];
} else {
if( in_array( $i, $existing_ids ) ) $i++; // Adding +1 to $i since the ID is already taken
$teamids[$team['teamName']] = (!empty($team['teamID']) && in_array($team['teamID'], $existing_ids)) ? $team['teamID'] : $i;
$team['teamID'] = (empty($team['teamID'])) ? $i : $team['teamID'];
if( empty($team['teamID'] ) ) $i++;
}
array_push($teams_with_ids, $team);
}
1

Другие решения

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

$arr = array(
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '12', 'teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '', 'teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '', 'teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '', 'teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> '', 'teamName' => 'Slovakia', 'playerName'=>'Ivan'),

);

function getTeamIdFromName($arr, $teamName){
foreach($arr as $element){
if($element["teamName"] == $teamName && !empty($element["teamID"])){
return $element["teamID"];
}
}
return false;
}

function getNewTeamId($arr){
$existingIds = array_unique(array_column($arr, 'teamID'));
$id = 1;
while(in_array($id, $existingIds)) $id++;
return $id;
}foreach($arr as $k=>$element){
if(empty($element['teamId'])){
if(!($id = getTeamIdFromName($arr, $element["teamName"]))){
$id = getNewTeamId($arr);
}
$arr[$k]['teamID'] = $id;
}
}

Обратите внимание, что вы должны использовать кавычки для ключей массива и «>» для имен игроков, если они отсутствуют.

0

Это напрямую манипулирует исходным массивом и добавляет «отсутствующие» идентификаторы:

$teams = [];
$id_counter = 1;

$teamids = [];
foreach($arr as $entry) {
$teamids[] = $entry['teamID'];
}
array_unique($teamids);

foreach($arr as &$entry) {
if(!isset($teams[$entry['teamName']])) {
if($entry['teamID'] == '') {
while(in_array($id_counter, $teamids)) {
$id_counter++;
}
$teamids[] = $id_counter;
array_unique($teamids);
$teams[$entry['teamName']] = $id_counter;
}
else {
$teams[$entry['teamName']] = $entry['teamID'];
$teamids[] = $entry['teamID'];
array_unique($teamids);
}
}
$entry['teamID'] = $teams[$entry['teamName']];
}
unset($entry);
0

Чтобы избежать повторного поиска для teamID значения при обходе вашего входного массива, рекомендуется сначала / отдельно создать массив поиска.

Создание массива поиска, безусловно, более утомительно, чем его применение. Я прокомментировал значения временного массива, чтобы помочь вам понять, что генерируется на каждом шаге. Используя соответствующие имена переменных и функции массива (которые улучшают понимание кода), я думаю, что это не должно быть слишком сложным для подражания.

Для тех, кто не может сравнить производительность кода, ответ MarcusKreusch в настоящее время является единственным другим ответом, который дает правильные результаты. Однако на каждой итерации входного массива выполняется два сканирования (в рамках вызовов пользовательских функций) входного массива. Мое решение является более прямым и эффективным, потому что оно использует меньше повторных вызовов функций / циклов / условий.

Код: (демонстрация)

$lookup=array_column($arr,'teamID','teamName'); // var_export($lookup); // ['USA'=>'','Norway'=>'','Germany'=>'','Slovakia'=>'']
$positive_ids=array_filter(array_flip(array_column($arr,'teamName','teamID'))); // var_export($positive_ids); // ['Norway'=>12]
$i=0;
foreach($lookup as $name=>&$id){
if(isset($positive_ids[$name])){
$id=$positive_ids[$name];
}else{
while(in_array(++$i,$positive_ids));   // avoid collisions between existing and new ids
$id=$i;
}
}  // var_export($lookup);  // ['USA'=>1,'Norway'=>12,'Germany'=>2,'Slovakia'=>3]

foreach($arr as &$row){
$row['teamID']=$lookup[$row['teamName']];  // make id assignments
}

Результат: (модифицированный $arr теперь содержит …)

array(
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> 12,'teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> 12,'teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> 1,'teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> 2,'teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> 3,'teamName' => 'Slovakia', 'playerName'=>'Ivan')
)


Я хочу уточнить, что мое решение правильно обрабатывает два возможных и проблемных входных массива:

Проблема: пробелы в увеличенных идентификаторах

$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'=>'Ivan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '12','teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'=>'Alexander')
);

При внимательном рассмотрении вы увидите, что первое появление Norway без идентификатора. Любой метод, который зацикливает массив для назначения новых ключей, будет считать Norway нуждается в увеличении id, поскольку Norway идет после USA (который утверждает, 1), NorwayИдентификатор 2, затем Slovakia дано 3, Тогда id за Norway перезаписывается как 12, В заключение, Germany дано 4, Это оставляет пробелы в приращении.

Проблема: Столкновение между существующими и новыми идентификаторами.

$arr = array(
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'John'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Peter'),
array('teamID'=> '2','teamName' => 'Norway', 'playerName'=>'Zigmund'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Parker'),
array('teamID'=> '','teamName' => 'Norway', 'playerName'=>'Jan'),
array('teamID'=> '','teamName' => 'USA', 'playerName'=>'Hector'),
array('teamID'=> '','teamName' => 'Germany', 'playerName'=>'Alexander'),
array('teamID'=> '','teamName' => 'Slovakia', 'playerName'=>'Ivan')
);

Без проверки на конфликты идентификаторов, приведенный выше массив сгенерирует две команды с 2 как идентификатор

0

Не лучшим образом, но работает:

$arr = array(
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'John'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Peter'),
array('teamID' => '12', 'teamName' => 'Norway', 'playerName' => 'Zigmund'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Parker'),
array('teamID' => '4', 'teamName' => 'Norway', 'playerName' => 'Jan'),
array('teamID' => '', 'teamName' => 'USA', 'playerName' => 'Hector'),
array('teamID' => '', 'teamName' => 'Germany', 'playerName' => 'Alexander'),
array('teamID' => '', 'teamName' => 'Slovakia', 'playerName' => 'Ivan'),
);

// build array with existing ids
$ids = array();
foreach ($arr as $row) {
if ($row['teamID'] !== '') {
$ids []= $row['teamID'];
}
}

// start from
$id = 1;
foreach ($arr as $i => $row) {
if ($row['teamID'] === '') {
while(in_array($id, $ids)) {
$id++;
}
// put id in $arr
$arr[$i]['teamID'] = $id;
$id++;
}
}

var_dump($arr);
-1
По вопросам рекламы [email protected]