在PHP开发的实际场景中,我们经常会遇到需要根据关联数组的出现频率来对主数组进行排序的需求,比如统计用户提交的标签出现次数后按次数从高到低排序,或是统计订单中的商品分类出现频率并排序展示。这种需求的核心是先统计关联数组的频率,再基于频率值对主数组进行排序。

实现思路梳理
要实现根据关联数组频率对主数组排序,整体可以分为三个核心步骤:
- 第一步:遍历关联数组,统计每个元素出现的频率,生成频率映射数组
- 第二步:定义排序规则,基于频率映射数组中的值对主数组进行排序
- 第三步:执行排序操作,得到最终的排序结果
具体实现步骤
1. 统计关联数组的频率
我们可以使用array_count_values函数快速统计数组中每个值出现的次数,这个函数会返回一个关联数组,键是原数组的元素值,值是该元素出现的次数。
<?php // 定义主数组,这里以用户提交的标签数组为例 $mainArray = ['php', 'java', 'php', 'python', 'java', 'php', 'go', 'python']; // 统计每个标签的出现频率 $frequencyMap = array_count_values($mainArray); // 输出频率映射数组 print_r($frequencyMap); ?>
上述代码的输出结果如下,清晰展示了每个标签的出现次数:
Array
(
[php] => 3
[java] => 2
[python] => 2
[go] => 1
)
2. 基于频率对主数组排序
PHP的usort函数可以自定义排序规则,我们可以在排序回调函数中通过频率映射数组获取对应元素的频率,再比较两个频率的大小来确定排序顺序。
<?php
$mainArray = ['php', 'java', 'php', 'python', 'java', 'php', 'go', 'python'];
$frequencyMap = array_count_values($mainArray);
// 使用usort自定义排序规则,按频率从高到低排序,频率相同则按字母顺序排序
usort($mainArray, function($a, $b) use ($frequencyMap) {
$freqA = $frequencyMap[$a];
$freqB = $frequencyMap[$b];
// 先比较频率,频率高的排在前面
if ($freqA != $freqB) {
return $freqB - $freqA;
}
// 频率相同则按字母升序排列
return strcmp($a, $b);
});
print_r($mainArray);
?>
上述代码的输出结果如下,主数组已经按照标签出现频率从高到低完成排序:
Array
(
[0] => php
[1] => php
[2] => php
[3] => java
[4] => java
[5] => python
[6] => python
[7] => go
)
3. 保留原数组键名的排序方式
如果主数组是关联数组,需要保留原有的键名,可以使用uasort函数,它的用法和usort类似,但不会重新索引数组的键名。
<?php
// 带键名的主数组
$mainArray = [
'a' => 'php',
'b' => 'java',
'c' => 'php',
'd' => 'python',
'e' => 'java',
'f' => 'php',
'g' => 'go',
'h' => 'python'
];
$frequencyMap = array_count_values($mainArray);
// 使用uasort保留键名排序
uasort($mainArray, function($a, $b) use ($frequencyMap) {
$freqA = $frequencyMap[$a];
$freqB = $frequencyMap[$b];
if ($freqA != $freqB) {
return $freqB - $freqA;
}
return strcmp($a, $b);
});
print_r($mainArray);
?>
输出结果会保留原有的键名,排序后的数组结构如下:
Array
(
[a] => php
[c] => php
[f] => php
[b] => java
[e] => java
[d] => python
[h] => python
[g] => go
)
注意事项
- 如果主数组中存在非字符串或整数的元素,
array_count_values函数会报错,需要先对元素类型做处理 - 排序规则的自定义可以根据实际需求调整,比如改为按频率从低到高排序,只需要调整返回值的计算逻辑即可
- 当数组元素数量较大时,这种实现方式的性能表现良好,因为频率统计和排序的时间复杂度都在可接受范围内
这种基于频率排序的方式适用于大多数PHP数组排序场景,开发者可以根据实际需求灵活调整排序规则,满足不同的业务要求。