此问题旨在作为有关在PHP中排序数组的问题的参考。很容易认为您的特定情况是独一无二的,值得一个新问题,但大多数实际上是本页面上其中一个解决方案的微小变化。如果您的问题与此问题的副本相同,请仅在您能够解释为何与以下所有问题明显不同时才要求重新打开您的问题。如何在PHP中对数组进行排序?如何在PHP中对复杂数组进行排序?如何在PHP中对对象数组进行排序?基本的一维数组; 含。多维数组,包括 对象数组; 含。基于另一个排序一个数组使用SPL排序稳定的排序有关使用PHP现有函数的实际答案,请参阅1.,有关排序算法的学术详细答案(PHP的函数实现以及您可能需要哪些非常复杂的案例),请参阅参考资料2。
3 回答
万千封印
TA贡献1891条经验 获得超3个赞
稳定的排序
假设你有一个像这样的数组:
['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']
而现在你只想对第一个字母进行排序:
usort($array, function($a, $b) { return strcmp($a[0], $b[0]);});
结果如下:
['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']
那种不稳定!
敏锐的观察者可能已经注意到,数组排序算法(QuickSort)没有产生稳定的结果,并且没有保留相同第一个字母的单词之间的原始顺序。这个案例很简单,我们应该比较整个字符串,但是我们假设你的用例更复杂,比如不同字段上的两个连续排序不应该抵消彼此的工作。
施瓦茨变换
Schwartzian变换,也称为decorate-sort-undecorate习语,使用固有的不稳定排序算法实现稳定排序。
首先,使用包含主键(值)和辅助键(其索引或位置)的另一个数组来装饰每个数组元素:
array_walk($array, function(&$element, $index) { $element = array($element, $index); // decorate});
这会将数组转换为:
[ ['Kale', 0], ['Kaleidoscope', 1], ['Aardvark', 2], ['Apple', 3], ['Leicester', 4], ['Lovely', 5]]
现在,我们调整比较步骤; 我们再次比较第一个字母,但如果它们相同,则使用二级密钥保留原始排序:
usort($array, function($a, $b) { // $a[0] and $b[0] contain the primary sort key // $a[1] and $b[1] contain the secondary sort key $tmp = strcmp($a[0][0], $b[0][0]); if ($tmp != 0) { return $tmp; // use primary key comparison results } return $a[1] - $b[1]; // use secondary key});
之后,我们不合理:
array_walk($array, function(&$element) { $element = $element[0];});
最终结果:
['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']
重用怎么样?
您必须重写比较函数才能使用转换后的数组元素; 您可能不想编辑精细的比较函数,因此这里是比较函数的包装器:
function stablecmp($fn){ return function($a, $b) use ($fn) { if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) { return $tmp; } else { return $a[1] - $b[1]; } };}
让我们使用这个函数编写排序步骤:
usort($array, stablecmp(function($a, $b) { return strcmp($a[0], $b[0]);}));
瞧!您的原始比较代码又回来了。
- 3 回答
- 0 关注
- 958 浏览
添加回答
举报
0/150
提交
取消