Я использую usort для сортировки массива с ассоциативным массивом внутри каждого элемента.
Когда все значения, которые я сортирую в массиве, одинаковы, тогда он все еще меняет положение элементов в массиве, есть ли способ предотвратить это?
Например, это:
array( array('name' => 'Ben', 'authn_weight' => 85.3), array('name' => 'Josh', 'authn_weight' => 85.3), array('name' => 'Fred', 'authn_weight' => 85.3) );
Может быть изменено на следующее:
array( array('name' => 'Josh', 'authn_weight' => 85.3), array('name' => 'Ben', 'authn_weight' => 85.3), array('name' => 'Fred', 'authn_weight' => 85.3) );
Это функция сортировки:
private function weightSortImplementation($a, $b){ $aWeight = $a['autn_weight']; $bWeight = $b['autn_weight']; if ($aWeight == $bWeight) { return 0; } return ($aWeight < $bWeight) ? 1 : -1; }
Я проверил, что функция weightSortImplementation
всегда возвращает 0, показывая, что они одинаковы. Итак, почему это все еще переупорядочивает массив?
Ага, случай Шварцского преобразования .
Он состоит в основном из трех шагов:
Вот он (я изменил его в вашем конкретном случае использования):
function decorate(&$v, $k) { $v['authn_weight'] = array($v['authn_weight'], $k); } function undecorate(&$v, $k) { $v['authn_weight'] = $v['authn_weight'][0]; } array_walk($a, 'decorate'); usort($a, 'weightSortImplementation'); array_walk($a, 'undecorate');
Трюк заключается в следующем утверждении:
array($x, 0) < array($x, 1)
Это то, что поддерживает правильный порядок вашего массива. И, рекурсии не требуется 🙂
Из документации :
Если два члена сравниваются как равные, их относительный порядок в отсортированном массиве не определен.
Вы можете использовать эту функцию [источник], которая сохраняет порядок в случае, когда два элемента равны:
function mergesort(&$array, $cmp_function = 'strcmp') { // Arrays of size < 2 require no action. if (count($array) < 2) return; // Split the array in half $halfway = count($array) / 2; $array1 = array_slice($array, 0, $halfway); $array2 = array_slice($array, $halfway); // Recurse to sort the two halves mergesort($array1, $cmp_function); mergesort($array2, $cmp_function); // If all of $array1 is <= all of $array2, just append them. if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) { $array = array_merge($array1, $array2); return; } // Merge the two sorted arrays into a single sorted array $array = array(); $ptr1 = $ptr2 = 0; while ($ptr1 < count($array1) && $ptr2 < count($array2)) { if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) { $array[] = $array1[$ptr1++]; } else { $array[] = $array2[$ptr2++]; } } // Merge the remainder while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++]; while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++]; return; }