Группировать и сортировать массив объектов по 2 параметрам - PullRequest
3 голосов
/ 26 февраля 2011

У меня есть массив объектов, которые я хочу отсортировать на основе одного свойства, а затем «группировать вместе» на основе другого свойства.В приведенном ниже примере я хотел бы, чтобы они были отсортированы по $sequence и сгруппированы по $artist.

// урезанная версия моего класса:

<?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>";}

?>

Обафункции сортировки, которые у меня есть в классе cmp_myclass_sequence и cmp_myclass_artist, хорошо работают сами по себе.Но я не уверен, как сгруппировать массив таким образом: сначала идут все художники A, затем B и так далее.Среди художников А объекты должны быть отсортированы по последовательности int этого объекта.

Короче говоря, это результат, который я ищу:

/*
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 ) 
*/

Ответы [ 3 ]

4 голосов
/ 08 января 2015

Вы можете сделать это с вкусностями Узо :

$result = Arrays::sort($arr, Comparator::compound(
    Comparator::compareBy('artist'),
    Comparator::compareBy('sequence')
));

http://ouzo.readthedocs.org/en/latest/utils/comparators.html

2 голосов
/ 26 февраля 2011

Вы можете сделать это легко с помощью одной функции сравнения:

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');
0 голосов
/ 26 февраля 2011

Как насчет функции сравнения, которая выглядит следующим образом:

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;
}

Таким образом, вы начинаете сравнение по исполнителю, и если исполнитель совпадает, вы сравниваете по порядку.Я думаю, что это должно работать.

...