如果两个成员比较相等,则它们在排序数组中的相对顺序是未定义的。
另外,
引入了一种新的排序算法。cmp_function不会为比较相等的元素保留原始顺序。
那么我的问题是:如果两个元素相等(例如用户定义的函数返回0),会发生什么?
我正在使用此函数,显然相等的项目随机排列在排序后的数组中。
在对我的数组进行排序
时,我也发现了同样的问题,于是我找到了一些自定义函数,因为php
有一些限制,不能使用已定义的sorting
函数。
http://php.net/manual/en/function.uasort.php#Vd114535
PHP 7对小型数组(<16)使用稳定的排序算法, 但对于较大的数组,该算法仍然不稳定。 此外,PHP不能保证使用*sort()进行排序是否稳定https://bugs.php.net/bug.php?id=53341。
这个函数对于相等的值保持顺序(来自我的CMS EFFCORE的示例):
function array_sort_by_number(&$array, $key = 'weight', $order = 'a') {
$increments = [];
foreach ($array as &$c_item) {
$c_value = is_object($c_item) ? $c_item->{$key} : $c_item[$key];
if ($order === 'a') $increments[$c_value] = array_key_exists($c_value, $increments) ? $increments[$c_value] - .0001 : 0;
if ($order === 'd') $increments[$c_value] = array_key_exists($c_value, $increments) ? $increments[$c_value] + .0001 : 0;
if (is_object($c_item)) $c_item->_synthetic_weight = $c_value + $increments[$c_value];
else $c_item['_synthetic_weight'] = $c_value + $increments[$c_value];
}
uasort($array, function ($a, $b) use ($order) {
if ($order === 'a') return (is_object($b) ? $b->_synthetic_weight : $b['_synthetic_weight']) <=> (is_object($a) ? $a->_synthetic_weight : $a['_synthetic_weight']);
if ($order === 'd') return (is_object($a) ? $a->_synthetic_weight : $a['_synthetic_weight']) <=> (is_object($b) ? $b->_synthetic_weight : $b['_synthetic_weight']);
});
foreach ($array as &$c_item) {
if (is_object($c_item)) unset($c_item->_synthetic_weight);
else unset($c_item['_synthetic_weight']);
}
return $array;
}
它适用于数组和对象。 它添加了一个合成键,按照该键排序,然后将其删除。
$test = [
'a' => ['weight' => 4],
'b' => ['weight' => 10],
'c' => ['weight' => 10],
'd' => ['weight' => 10],
'e' => ['weight' => 4],
];
$test_result = [
'b' => ['weight' => 10],
'c' => ['weight' => 10],
'd' => ['weight' => 10],
'a' => ['weight' => 4],
'e' => ['weight' => 4],
];
array_sort_by_number($test, 'weight', 'a');
print_R($test);
var_dump($test === $test_result);
$test = [
'a' => ['weight' => 4],
'b' => ['weight' => 10],
'c' => ['weight' => 10],
'd' => ['weight' => 10],
'e' => ['weight' => 4],
];
$test_result = [
'a' => ['weight' => 4],
'e' => ['weight' => 4],
'b' => ['weight' => 10],
'c' => ['weight' => 10],
'd' => ['weight' => 10],
];
array_sort_by_number($test, 'weight', 'd');
print_R($test);
var_dump($test === $test_result);
我也遇到了同样的问题,其中有2行具有相同的值,当应用排序函数时,它们的顺序会改变,而我不想要这种情况。我想根据它们的值对键进行排序,如果它们相等,则不更改顺序。所以这是我的解决方案-
// sample array
$arr = Array("a" => 0.57,"b" => 1.19,"c" => 0.57,"d" => 0.57,"e" => 0.57,"f" => 0.57,"g" => 0.57,"h" => 0.57,"i" => 0.99,"j" => 1.19,"k" => 1.19);
$multi_arr = [];
foreach ($arr as $k=>$val){
$multi_arr["$val"][] = array($k=>$val);
}
uksort($multi_arr, function ($a, $b) {
return $b > $a ? 1 : -1;
});
$s_arr = [];
foreach ($multi_arr as $k=>$val){
foreach($val as $p_id){
$p_arr = array_keys($p_id);
$s_arr[] = $p_arr[0];
}
}
print_r($s_arr);
输出-
数组([0] => b,[1] => j,[2] => k,[3] => i,[4] => a,[5] => c,[6] => d,[7] => e,[8] => f,[9] => g,[10] => h)
了解PHP在比较值相同时不关心顺序。
例如:
$temp=array("b"=>"10","c"=>"10","d"=>"10","e"=>"4");
如上所示,该数组有4个元素,其中3个具有相同的值,如b、c、d=10;arsort()
// arsort()函数按值降序对关联数组进行排序
如果print_r(arsort($temp))
输出:=> Array ( [b] => 10 [c] => 10 [d] => 10 [e] => 4 )
这意味着它返回排序后的等值数组,但保持相等值的位置(顺序)不变
但是
如果$temp=array("a"=>"4",b"=>"10","c"=>"10","d"=>"10","e"=>"4");
在上述数组中,b、c、d=10被限制在两个极端的左右数组中,其值小于中心(b、c、d=10)的值。
以上tmp的arsort输出为:
Array ( [c] => 10 [b] => 10 [d] => 10 [a] => 4 [e] => 4 )
它给出了中间部分即[c]数组在中心。 这意味着,如果相似值或相等值的数组被低值数组从两侧限制,或者第一个值比顺序低,则相等值的顺序将从三个数组值中的第一个作为中间值。
['b', 'a', 'c', 'b']
,并对其进行排序,那么会得到:['a','b','b','c']
。由于'b' == 'b'
,php无法保证哪个排在前面,因此排序顺序是“未定义的”,但由于它们相等,这是否重要?usort()
按每个数组中元素的数量进行排序。因此,如果我有 0=>(1, 2), 1=>(1, 3), 2=>(1, 2), 3=>(1, 3)
,则顺序变为 2=>(1, 2), 1=>(1, 3), 3=>(1, 3), 0=>(1, 2)
,我想知道为什么 0 被移到了最后。 - linkyndy0
移动到源数组中也会将其移动到结果数组中的另一个位置。 - Alexander Varwijk