如何按角色数量及字母优先级对用户关联数组数组排序
PHP按指定角色规则排序用户数组
问题分析
给定的用户数组中部分角色存在嵌套结构,需按以下规则排序:
- 仅拥有
admin角色的用户排在最前 - 其次是拥有
admin+字母序最靠前的额外角色的用户 - 接着是拥有
admin+该靠前角色+下一个字母序角色的用户 - 再是拥有
admin+下一个字母序角色的用户,以此类推
解决方案
步骤1:统一提取用户角色
编写辅助函数处理可能的嵌套结构,确保正确获取每个用户的所有角色键名:
function getUserRoles($user) { $roles = $user['roles']; // 处理嵌套的roles结构 if (isset($roles['roles'])) { $roles = $roles['roles']; } return array_keys($roles); }
步骤2:确定全局额外角色优先级
收集所有用户的非admin角色,去重后按字母排序得到全局角色优先级顺序:
$users = [ [ "name" => "Marcos", "roles" => [ "admin" => "2023-11-16T10:23:45Z", "reader" => "2023-11-16T10:24:23Z" ] ], [ "name" => "Roberto", "roles" => [ "admin" => "2023-11-16T10:23:45Z", ] ], [ "name" => "Jaime", "roles" => [ "admin" => "2023-11-16T10:23:45Z", "writer" => "2023-11-16T10:24:23Z" ] ], [ "name" => "Xabier", "roles" => [ "roles" => [ "admin" => "2023-11-16T10:23:45Z", "writer" => "2023-11-16T10:24:23Z", "reader" => "2023-11-16T10:24:23Z" ] ] ] ]; // 收集所有非admin角色 $allExtraRoles = []; foreach ($users as $user) { $roles = getUserRoles($user); $extraRoles = array_filter($roles, fn($role) => $role !== 'admin'); $allExtraRoles = array_merge($allExtraRoles, $extraRoles); } $allExtraRoles = array_unique($allExtraRoles); sort($allExtraRoles); // 按字母排序得到优先级顺序
步骤3:自定义排序逻辑
使用usort结合自定义比较函数,按规则对用户数组排序:
usort($users, function($a, $b) use ($allExtraRoles) { // 获取当前用户的非admin角色并排序 $aRoles = getUserRoles($a); $aExtra = array_filter($aRoles, fn($r) => $r !== 'admin'); sort($aExtra); $aExtraCount = count($aExtra); $bRoles = getUserRoles($b); $bExtra = array_filter($bRoles, fn($r) => $r !== 'admin'); sort($bExtra); $bExtraCount = count($bExtra); // 仅admin的用户排最前 if ($aExtraCount === 0) { return -1; } if ($bExtraCount === 0) { return 1; } // 按全局角色优先级顺序逐一检查 foreach ($allExtraRoles as $role) { $aHas = in_array($role, $aExtra); $bHas = in_array($role, $bExtra); if ($aHas && !$bHas) { return -1; // A有当前优先级角色,B没有,A排前 } if (!$aHas && $bHas) { return 1; // B有当前优先级角色,A没有,B排前 } } // 角色组合完全匹配时,额外角色少的排前 return $aExtraCount - $bExtraCount; });
排序结果
执行代码后,用户数组的最终顺序为:
- Roberto(仅admin)
- Marcos(admin+reader)
- Xabier(admin+reader+writer)
- Jaime(admin+writer)
内容的提问来源于stack exchange,提问作者Marcos 'HaddocK' Pérez
相关产品推荐
相关产品推荐

