Функция Usort для сортировки и группировки

У меня есть этот массив.

Array
(
    [0] => Array
        (
            [name] => SUNDERLAND
            [pts] => 2
            [gd] => -4
            [group] => A
        )

    [1] => Array
        (
            [name] => NEWCASTLE
            [pts] => 2
            [gd] => -3
            [group] => C
        )

    [2] => Array
        (
            [name] => STOKE CITY
            [pts] => 2
            [gd] => -2
            [group] => B
        )

    [3] => Array
        (
            [name] => WATFORD
            [pts] => 3
            [gd] => -2
            [group] => A
        )

    [4] => Array
        (
            [name] => TOTTENHAM
            [pts] => 3
            [gd] => -1
            [group] => B
        )

    [5] => Array
        (
            [name] => CHELSEA
            [pts] => 4
            [gd] => -5
            [group] => C
        )

    [6] => Array
        (
            [name] => NORWICH
            [pts] => 4
            [gd] => -3
            [group] => D
        )

    [7] => Array
        (
            [name] => WEST BROM
            [pts] => 4
            [gd] => -4
            [group] => D
        )

)

Я должен отсортировать и сгруппировать элементы этого массива по некоторым критериям.

В этой же группе первым ИМЯ является имя с большим параметром pts (параметр DESC by pts). Если параметры pts одинаковы по параметру gd (DESC по параметру gd)

Названия команд с одной группой вместе.

Name        pts     gd      group

WATFORD     3       -2      A
SUNDERLAND  2       -4      A
TOTTENHAM   3       -1      B
STOKE CITY  2       -2      B
CHELSEA     4       -5      C
NEWCASTLE   2       -3      C
NORWICH     4       -3      D
WEST BROM   4       -4      D

в этот момент я могу отсортировать по pts и gd следующим образом:

<?php
function sortByOrder($a, $b){
    $c = $a['pts'] - $b['pts'];
    $c .= $a['gd'] - $b['gd'];
    return $c;
}
usort($all_teams_nf, 'sortByOrder');

foreach($all_teams_nf as $myarr){
    foreach($myarr as $key => $team){
        if($key!="pts" and $key!="gd" and $key!="group"){
            $all_teams[] = $team;
        }
    }
}

$all_teams = array_reverse($all_teams);
?>

Пожалуйста, помогите объединить по группам, а затем в каждой группе порядок по очкам и GD. (В конечном итоге мне нужно показать название группы и название команды!

A   
    WATFORD 
    SUNDERLAND
B
    TOTTENHAM
    STOKE CITY
C
    CHELSE
    NEWCASTLE
D
    NORWICH
    WEST BROM

3 ответа

Я хотел бы использовать array_multisort вместо usort за это. Сначала сгруппируйте строки по ключу группы. Тогда используйте array_multisort на каждой группе. Наконец вы можете использовать ksort если вам нужно, чтобы группы появлялись также в отсортированном порядке.

$arraysByGroup = array();

// group by group key
foreach($array as $element) {
    $arraysByGroup[$element['group']][] = $element;
}

// sort each group by name, pts, gd
foreach($arraysByGroup as &$group) {

    $name = $pts = $gd = array();

    foreach($group as $key => $value) {
        $name[$key] = $value['name'];
        $pts[$key] = $value['pts'];
        $gd[$key] = $value['gd'];
    }

    array_multisort($name, SORT_ASC, $pts, SORT_DESC, $gd, SORT_DESC, $group);
}

ksort($arraysByGroup);
print_r($arraysByGroup);

Давай проверим

это мой массив:

$array = array( array("name" => "SUNDERLAND", "pts" => "2", "gd" => "-4", "group" => "A"), 
                array("name" => "NEWCASTLE", "pts" => "2", "gd" => "-3", "group" => "C"), 
                array("name" => "STOKE CITY", "pts" => "2", "gd" => "-2", "group" => "B"), 
                array("name" => "WATFORD", "pts" => "3", "gd" => "-2", "group" => "A"), 
                array("name" => "TOTTENHAM", "pts" => "3", "gd" => "-1", "group" => "B"), 
                array("name" => "CHELSEA", "pts" => "4", "gd" => "-5", "group" => "C"), 
                array("name" => "NORWICH", "pts" => "4", "gd" => "-3", "group" => "D"),
                array("name" => "WEST BROM", "pts" => "4", "gd" => "-4", "group" => "D")
);

это мой результат:

Array
(
    [A] => Array
        (
            [0] => Array
                (
                    [name] => SUNDERLAND
                    [pts] => 2
                    [gd] => -4
                    [group] => A
                )

            [1] => Array
                (
                    [name] => WATFORD
                    [pts] => 3
                    [gd] => -2
                    [group] => A
                )

        )

    [B] => Array
        (
            [0] => Array
                (
                    [name] => STOKE CITY
                    [pts] => 2
                    [gd] => -2
                    [group] => B
                )

            [1] => Array
                (
                    [name] => TOTTENHAM
                    [pts] => 3
                    [gd] => -1
                    [group] => B
                )

        )

    [C] => Array
        (
            [0] => Array
                (
                    [name] => CHELSEA
                    [pts] => 4
                    [gd] => -5
                    [group] => C
                )

            [1] => Array
                (
                    [name] => NEWCASTLE
                    [pts] => 2
                    [gd] => -3
                    [group] => C
                )

        )

    [D] => Array
        (
            [0] => Array
                (
                    [name] => NORWICH
                    [pts] => 4
                    [gd] => -3
                    [group] => D
                )

            [1] => Array
                (
                    [name] => WEST BROM
                    [pts] => 4
                    [gd] => -4
                    [group] => D
                )

        )

)

В группе A I требуется DESC по pts - есть ASC. В группе B то же самое. В группе C & D результаты в порядке.

Возможно, вам это больше не нужно, но чтобы помочь кому-то найти что-то похожее, я бы решил эту проблему с заказом именно так.

      // data
$my_array = array(
    array( 'name' => 'SUNDERLAND','pts'=> 2, 'gd' => -4, 'group' => 'A' ),
    array( 'name' => 'NEWCASTLE', 'pts' => 2, 'gd' => -3, 'group' => 'C' ),
    array( 'name' => 'STOKE CITY', 'pts' => 2, 'gd' => -2, 'group' => 'B' ),
    array( 'name' => 'WATFORD', 'pts' => 3, 'gd' => -2, 'group' => 'A' ),
    array( 'name' => 'TOTTENHAM', 'pts' => 3, 'gd' => -1,'group' => 'B'),
    array( 'name' => 'CHELSEA', 'pts' => 4, 'gd' => -5, 'group' => 'C' ),
    array( 'name' => 'NORWICH', 'pts' => 4, 'gd' => -3, 'group' => 'D' ),
    array( 'name' => 'WEST BROM','pts' => 4,'gd' => -4, 'group'=> 'D' )
);

// sorting by criterias (group; points and gd);
usort( $my_array, function( $a, $b ) {
    if ( $a['group'] === $b['group'] ) {
      if ( $a['pts'] === $b['pts'] ) {
          return $a['gd'] < $b['gd']; // order by gd
      }  else {
        return $a['pts'] < $b['pts']; // order by points
      }
    } 
    return $a['group'] > $b['group']; // order by group
});

// Creating a new array with only desired data.
$final = [];
foreach ( $my_array as $team ) {
    if ( empty( $final[ $team['group'] ] ) ) $final[ $team['group'] ] = [];
    array_push( $final[ $team['group'] ], $team['name'] );
}

print_r( $final );
Другие вопросы по тегам