I have an array of objects which I want to sort based on one property, and then kind of 'group together' based on another property. In the example below, I would like them sorted based on $sequence, and grouped based on $artist

// a stripped down version of my class :

<?php
class myClass
{
    public $sequence;
    public $artist;

    function __construct($sequence,$artist)
    {
        $this->sequence=$sequence;
        $this->artist=$artist;
    }

    static function cmp_myclass_sequence($a, $b)
    {
        $a_seq = $a->sequence;
        $b_seq = $b->sequence;
        if ($a_seq == $b_seq) {
            return 0;
        }
        return ($a_seq > $b_seq) ? +1 : -1;
    }
    static function cmp_myclass_artist($a, $b)
    {
        $a_art = strtolower($a->artist);
        $b_art = strtolower($b->artist);
        if ($a_art == $b_art) {
            return 0;
        }
        return ($a_art > $b_art) ? +1 : -1;
    }
}

//some objects of my class which am using for testing :

$myObj1 = new myClass(1,'A');
$myObj2 = new myClass(1,'B');
$myObj3 = new myClass(1,'C');
$myObj4 = new myClass(2,'A');
$myObj5 = new myClass(2,'B');
$myObj6 = new myClass(2,'C');
$myObj7 = new myClass(4,'A');
$myObj8 = new myClass(5,'A');
$myObj9 = new myClass(3,'B');
$myObj10 = new myClass(3,'G');
$myObj11= new myClass(3,'A');

$myArr=array($myObj1,$myObj2,$myObj3,$myObj4,$myObj5,$myObj6,$myObj7,$myObj8,$myObj9,$myObj10,$myObj11);

echo "My Array Before sort : <br>";
foreach ($myArr as $obj){ print_r($obj); echo "<br>"; }

usort($myArr, array("myClass", "cmp_myclass_sequence"));
//usort($myArr, array("myClass", "cmp_myclass_artist"));


echo "My Array AFTER sort : <br>";
foreach ($myArr as $obj){ print_r($obj); echo "<br>";}

?>

Both the sorting functions that I have in the class ,'cmp_myclass_sequence' and 'cmp_myclass_artist' work well on their own. But I am not sure how to get the array grouped in this way : All the A artists come first, then the B and so on. Amongst the A artists, the objects should be sorted by the sequence int of that object.

In short this is the result that am looking for :

/*
My Array AFTER sort : 

myClass Object ( [sequence] => 1 [artist] => A )
myClass Object ( [sequence] => 2 [artist] => A )
myClass Object ( [sequence] => 3 [artist] => A )
myClass Object ( [sequence] => 4 [artist] => A )
myClass Object ( [sequence] => 5 [artist] => A )
myClass Object ( [sequence] => 1 [artist] => B )
myClass Object ( [sequence] => 2 [artist] => B )
myClass Object ( [sequence] => 3 [artist] => B )
myClass Object ( [sequence] => 1 [artist] => C )
myClass Object ( [sequence] => 2 [artist] => C )
myClass Object ( [sequence] => 3 [artist] => G ) 
*/

many thanks for reading through.

share|improve this question

75% accept rate
feedback

2 Answers

up vote 1 down vote accepted

You can do this easily with one compare function:

function sort_c_arr($item_1, $item_2)
{
   if($item_1->artist != $item_2->artist)
   {
      return strcmp($item_1->artist, $item_2->artist);
   }
   return $item_1->sequence - $item_2->sequence;
}
// ...
usort($arr, 'sort_c_arr');
share|improve this answer
worked as required , first attempt, thanks a lot! – SIndhu Feb 26 '11 at 14:31
feedback

What about a compare function going like this :

function cmp_myclass_artist_then_sequence($a, $b) {
    $a_art = strtolower($a->artist);
    $b_art = strtolower($b->artist);
    if ($a_art == $b_art) {
        return cmp_myclass_sequence($as, $b);
    }
    return ($a_art > $b_art) ? +1 : -1;
}

This way you start comparing by artist, and if the artist is the same, you compare by sequence. I think it should work.

share|improve this answer
Hi Krtek, I did try to make this work in the code that I had put in my question, but ran into some errors. – SIndhu Feb 26 '11 at 14:34
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.