Question

What is an elegant way to sort objects in PHP? I would love to accomplish something similar to this.

$sortedObjectArary = sort($unsortedObjectArray, $Object->weight);

Basically specify the array I want to sort as well as the field I want to sort on. I looked into multidimensional array sorting and there might be something useful there, but I don't see anything elegant or obvious.

Was it helpful?

Solution

Almost verbatim from the manual:

function compare_weights($a, $b) { 
    if($a->weight == $b->weight) {
        return 0;
    } 
    return ($a->weight < $b->weight) ? -1 : 1;
} 

usort($unsortedObjectArray, 'compare_weights');

If you want objects to be able to sort themselves, see example 3 here: http://php.net/usort

OTHER TIPS

For php >= 5.3

function osort(&$array, $prop)
{
    usort($array, function($a, $b) use ($prop) {
        return $a->$prop > $b->$prop ? 1 : -1;
    }); 
}

Note that this uses Anonymous functions / closures. Might find reviewing the php docs on that useful.

You can even build the sorting behavior into the class you're sorting, if you want that level of control

class thingy
{
    public $prop1;
    public $prop2;

    static $sortKey;

    public function __construct( $prop1, $prop2 )
    {
        $this->prop1 = $prop1;
        $this->prop2 = $prop2;
    }

    public static function sorter( $a, $b )
    {
        return strcasecmp( $a->{self::$sortKey}, $b->{self::$sortKey} );
    }

    public static function sortByProp( &$collection, $prop )
    {
        self::$sortKey = $prop;
        usort( $collection, array( __CLASS__, 'sorter' ) );
    }

}

$thingies = array(
        new thingy( 'red', 'blue' )
    ,   new thingy( 'apple', 'orange' )
    ,   new thingy( 'black', 'white' )
    ,   new thingy( 'democrat', 'republican' )
);

print_r( $thingies );

thingy::sortByProp( $thingies, 'prop1' );

print_r( $thingies );

thingy::sortByProp( $thingies, 'prop2' );

print_r( $thingies );

For that compare function, you can just do:

function cmp( $a, $b )
{ 
    return $b->weight - $a->weight;
} 

The usort function (http://uk.php.net/manual/en/function.usort.php) is your friend. Something like...

function objectWeightSort($lhs, $rhs)
{
   if ($lhs->weight == $rhs->weight)
     return 0;

   if ($lhs->weight > $rhs->weight)
     return 1;

   return -1;
}

usort($unsortedObjectArray, "objectWeightSort");

Note that any array keys will be lost.

You could use the usort() function and make your own comparison function.

$sortedObjectArray = usort($unsortedObjectArray, 'sort_by_weight');

function sort_by_weight($a, $b) {
    if ($a->weight == $b->weight) {
        return 0;
    } else if ($a->weight < $b->weight) {
        return -1;
    } else {
        return 1;
    }
}

Depending on the problem you are trying to solve, you may also find the SPL interfaces useful. For example, implementing the ArrayAccess interface would allow you to access your class like an array. Also, implementing the SeekableIterator interface would let you loop through your object just like an array. This way you could sort your object just as if it were a simple array, having full control over the values it returns for a given key.

For more details:

function PHPArrayObjectSorter($array,$sortBy,$direction='asc')
{
    $sortedArray=array();
    $tmpArray=array();
    foreach($this->$array as $obj)
    {
        $tmpArray[]=$obj->$sortBy;
    }
    if($direction=='asc'){
        asort($tmpArray);
    }else{
        arsort($tmpArray);
    }

    foreach($tmpArray as $k=>$tmp){
        $sortedArray[]=$array[$k];
    }

    return $sortedArray;

}

e.g =>

$myAscSortedArrayObject=PHPArrayObjectSorter($unsortedarray,$totalMarks,'asc');

$myDescSortedArrayObject=PHPArrayObjectSorter($unsortedarray,$totalMarks,'desc');

You can have almost the same code as you posted with sorted function from Nspl:

use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;

// Sort by property value
$sortedByWeight = sorted($objects, propertyGetter('weight'));

// Or sort by result of method call
$sortedByWeight = sorted($objects, methodCaller('getWeight'));

If you want to explore the full (terrifying) extent of lambda style functions in PHP, see: http://docs.php.net/manual/en/function.create-function.php

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top