Nando S.G.
Nando S.G.

Reputation: 35

Sort array by values in PHP mantaining relative positions

I'm using usort() and uasort(). I need to sort an array by values using a user-defined comparison function.

php.net/manual/en/function.usort.php

The doc says: Note:

If two members compare as equal, their relative order in the sorted array is undefined.

The question is: is there any PHP function that mantain the relative position of the equal elements?

Upvotes: 1

Views: 130

Answers (1)

stubsthewizard
stubsthewizard

Reputation: 352

The short answer is that PHP does not have a built in function to do this, so you will have to write one. Most of the time, it does not matter if the sort moves the element up or down if it is considered equal to the adjoining element. An example would be any array of integers. If two are the same, who cares what order they are in as long as they are together.

For the cases where you DO need to maintain the order of the lists, Sreid has written a very good function for this. It is actually on the usort page at php.net. I am pasting it here for your convenience. Be aware that I am giving sreid full credit for this code, and I have already mentioned where his original code can be found in a public forum:

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;

}

Upvotes: 1

Related Questions