Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP sort by arbitrary order [duplicate]

I need a function in php to sort a list of words according to an arbitrary ordering.

Any words in the list not in my predefined order should be sorted alphabetically at the end of the list.

Below is my first attempt, it is neither elegant or efficient. Can you suggest a better way to acheive this?

Thanks

public static function sortWords(&$inputArray){
    $order=array("Banana","Orange", "Apple", "Kiwi");
    sort($inputArray);
    for($i=0;$i<count($inputArray));$i++){
        $ac = $inputArray[$i];
        $position = array_search($ac,$order);
        if($position !== false && $i != $position){
            $temp=$inputArray[$position];
            $inputArray[$position]=$inputArray[$i];
            $inputArray[$i]=$temp;
        }
    }
}
like image 569
Chris Avatar asked Apr 12 '11 08:04

Chris


3 Answers

PHP provides the usort() and uksort() functions to allow you to write your own sorting routines. Of these two, you'll be wanting usort().

Both these functions expect you to write a stand-alone function, which takes as input two elements of the input array, and returns the order that they should be sorted into. The usort() function then runs its own sorting algorithm, calling your function as to establish the sorting order often as required until it has sorted the entire array.

So you'd write something like this....

function mycompare($a, $b) {
    if ($a == $b) {return 0;}
    $order=array("Banana","Orange", "Apple", "Kiwi");
    $position = array_search($a,$order);
    $position2 = array_search($b, $order);

    //if both are in the $order, then sort according to their order in $order...
    if ($position2!==false && $position!==false) {return ($position < $position2) ? -1 : 1;}
    //if only one is in $order, then sort to put the one in $order first...
    if($position!==false) {return -1;}
    if($position2!==false) {return 1;}

    //if neither in $order, then a simple alphabetic sort...
    return ($a < $b) ? -1 : 1;
}

...then just call usort($inputarray,'mycompare'); to sort them.

like image 179
Spudley Avatar answered Oct 19 '22 07:10

Spudley


public static function sortWords($inputArray){
    $order=array("Banana","Orange", "Apple", "Kiwi");
    $sorted_array = array_diff($inputArray,$order);
    sort($sorted_array);
    $rest_array = array_intersect($order,$inputArray);    
    $result = array_merge($rest_array,$sorted_array);
    return $result;
}

Haven't tested but try this.

like image 1
Headshota Avatar answered Oct 19 '22 07:10

Headshota


Probably slower than Headshota's solution, but just to provide you another (not tested) possibility:

function sortWordsCmp($a, $b) {
  $order=array("Banana","Orange", "Apple", "Kiwi");
  $a = array_search($a, $order);
  $b = array_search($b, $order);

  if ($a === $b)
    return 0;

  return (($b===false) || ($a < $b)) ? -1 : +1;
}

public static function sortWords($inputArray){
  usort($inputArray, 'sortWordsCmp');
  return $inputArray;
}
like image 1
Udo G Avatar answered Oct 19 '22 08:10

Udo G