PHP多维数组中按answer值降序排序scores子数组并保留键名
PHP多维数组按子数组元素值降序排序(保留键名)
问题描述
我有一个PHP多维数组,需要将每个顶级元素内的scores子数组按其元素的answer值从高到低降序排序,且保留所有数组键名。尝试通过循环和自定义排序函数实现,但未成功。
原数组
$array = [ 503 => [ 'scores' => [ 4573 => ['answer' => 100], 4574 => ['answer' => 60], 4575 => ['answer' => 100], 4576 => ['answer' => 80], 4577 => ['answer' => 40], 4578 => ['answer' => 20], 4579 => ['answer' => 60], 4580 => ['answer' => 100], 4581 => ['answer' => 60], 4582 => ['answer' => 60], 4583 => ['answer' => 80], 4584 => ['answer' => 80], ], 'category' => 'Category A', 'grade' => 70, 'color' => NULL ], 504 => [ 'scores' => [ 4585 => ['answer' => 40], 4586 => ['answer' => 100], 4587 => ['answer' => 80], 4588 => ['answer' => 60], 4589 => ['answer' => 100], 4590 => ['answer' => 40], 4591 => ['answer' => 80], 4592 => ['answer' => 60], 4593 => ['answer' => 60], 4594 => ['answer' => 100], 4595 => ['answer' => 100], 4596 => ['answer' => 80], ], 'category' => 'Category B', 'grade' => 75, 'color' => NULL ], 505 => [ 'scores' => [ 4597 =>['answer' => 20], 4598 =>['answer' => 80], 4599 =>['answer' => 100], 4600 =>['answer' => 60], 4601 =>['answer' => 20], 4602 =>['answer' => 20], 4603 =>['answer' => 100], 4604 =>['answer' => 40], 4605 =>['answer' => 60], 4606 =>['answer' => 100], 4607 =>['answer' => 80], 4608 =>['answer' => 20], ], 'category' => 'Category C', 'grade' => 58.3, 'color' => NULL, ] ];
尝试的代码
$temp_array_questions = $array_categorygrades; function sortq ($a, $b) { $highestcountfora = 0; $highestcountforb = 0; foreach ($a as $thescores) { if (is_array($thescores)) { foreach ($thescores as $thequestions) { if (is_array($thequestions)) { foreach ($thequestions as $theanswers) { if ($theanswers['answer'] > $highestcountfora) { $highestcountfora = $theanswers['answer']; } } } } } } foreach ($b as $thescores) { if (is_array($thescores)) { foreach ($thescores as $thequestions) { if (is_array($thequestions)) { foreach ($thequestions as $theanswers) { if ($theanswers['answer'] > $highestcountforb) { $highestcountforb = $theanswers['answer']; } } } } } } if ($highestcountfora === $highestcountforb) { return 0; } return ($highestcountfora < $highestcountforb)?1:-1; //if($a['scores']['answer']==$b['scores']['answer']) return 0; //return $a['scores']['answer'] < $b['scores']['answer']?1:-1; } uasort($temp_array_questions, 'sortq');
期望排序后的数组
[ 503 => [ 'scores' => [ 4573 => ['answer' => 100], 4575 => ['answer' => 100], 4580 => ['answer' => 100], 4576 => ['answer' => 80], 4583 => ['answer' => 80], 4584 => ['answer' => 80], 4574 => ['answer' => 60], 4579 => ['answer' => 60], 4581 => ['answer' => 60], 4582 => ['answer' => 60], 4577 => ['answer' => 40], 4578 => ['answer' => 20], ], 'category' => 'Category A', 'grade' => 70, 'color' => NULL ], 504 => [ 'scores' => [ 4586 => ['answer' => 100], 4589 => ['answer' => 100], 4594 => ['answer' => 100], 4595 => ['answer' => 100], 4587 => ['answer' => 80], 4591 => ['answer' => 80], 4596 => ['answer' => 80], 4588 => ['answer' => 60], 4592 => ['answer' => 60], 4593 => ['answer' => 60], 4585 => ['answer' => 40], 4590 => ['answer' => 40], ], 'category' => 'Category B', 'grade' => 75, 'color' => NULL ], 505 => [ 'scores' => [ 4599 =>['answer' => 100], 4603 =>['answer' => 100], 4606 =>['answer' => 100], 4598 =>['answer' => 80], 4607 =>['answer' => 80], 4600 =>['answer' => 60], 4605 =>['answer' => 60], 4604 =>['answer' => 40], 4597 =>['answer' => 20], 4601 =>['answer' => 20], 4602 =>['answer' => 20], 4608 =>['answer' => 20], ], 'category' => 'Category C', 'grade' => 58.3, 'color' => NULL, ] ]
解决方案
你之前的代码错误地对顶级数组元素进行排序,而不是每个顶级元素内部的scores子数组。正确的做法是遍历每个顶级元素,针对其scores子数组执行排序操作,同时用uasort保留键名。
以下是可行代码:
// 遍历原数组的每个顶级元素,使用引用直接修改原数组 foreach ($array as &$item) { // 对scores子数组按answer值降序排序,保留键名 uasort($item['scores'], function($a, $b) { // 太空船运算符实现降序:$b在前,$a在后 return $b['answer'] <=> $a['answer']; }); } // 解除引用,避免后续操作意外修改数组 unset($item);
代码说明
- 遍历与引用:使用
foreach ($array as &$item),通过引用直接修改原数组中的每个顶级元素,无需额外复制数组。 - uasort函数:该函数会对数组进行排序并保留原键名,正好符合需求。
- 匿名排序函数:用太空船运算符
<=>比较两个元素的answer值,$b['answer']在前实现降序排序;若值相等,会保持元素的原始相对顺序(稳定排序)。
内容的提问来源于stack exchange,提问作者Chris Ediger
相关产品推荐
相关产品推荐

