How can I sort IDs by multiple attributes

43 Views Asked by At

I have a multi-dimensional array of fencer ids with 3 attributes (see code below)

Array
(
    [0] => Array
        (
            [id] => 5255
            [ratio] => 1
            [point_difference] => -25
            [given] => 0
        )

    [1] => Array
        (
            [id] => 12256
            [ratio] => 0.5
            [point_difference] => -6
            [given] => 15
        )

    [2] => Array
        (
            [id] => 3473
            [ratio] => 0.83333333333333
            [point_difference] => -26
            [given] => 4
        )

    [3] => Array
        (
            [id] => 10478
            [ratio] => 0.16666666666667
            [point_difference] => -16
            [given] => 12
        )

    [4] => Array
        (
            [id] => 10256
            [ratio] => 0
            [point_difference] => -15
            [given] => 10
        )
)

I want to sort the fencers by ratio then point_difference then given

I tried multisport with array_columns but it messes up the keys of the column arrays and I need the keys to be the ids of the fencers so I can update the database with the ranking. ($ARRAY_fencers is the name of the multi-dimensional seen above)

//define columns
    $ratio_column = array_column($ARRAY_fencers, "ratio", "id");
    $point_diff_column = array_column($ARRAY_fencers, "point_difference", "id");
    $given_points_column = array_column($ARRAY_fencers, "given", "id");

     //start sorting the array array
    if (!array_multisort($ratio_column, SORT_DESC, SORT_NUMERIC, $point_diff_column, SORT_DESC, SORT_NUMERIC, $given_points_column, SORT_DESC, SORT_NUMERIC, $ARRAY_fencers)) {
        echo "CRITICAL ERROR: array_multisort could not complete the sort!";
    } 

If I try to get the keys of a column after sorting I just get 0, 1, 2, ... not the ids, but if I do it before the sort I get the IDs and perfectly but not in order obviously.

I aim to get the keys of one of the columns and use that array to update the database.

//update competitors temp ranking
    $temp_ranking_array = array_keys($given_points_column);

Is there something I'm doing wrong or should I use something else?

Thanks for your answer!

2

There are 2 best solutions below

1
AbraCadaver On BEST ANSWER

You don't need to index by id in the three array_column uses before the sort, and as you've seen they will be re-indexed after the sort anyway.

Associative (string) keys will be maintained, but numeric keys will be re-indexed.

So after the sort just do:

$ARRAY_fencers = array_column($ARRAY_fencers, null, "id");

To get the keys you can just use the first item without knowing it's key, or do it the way you're currently doing it:

$temp_ranking_array = array_keys(reset($ARRAY_fencers));

I don't create new variables unless I need them for another reason:

array_multisort(array_column($ARRAY_fencers, "ratio"), SORT_DESC, SORT_NUMERIC,
                array_column($ARRAY_fencers, "point_difference"), SORT_DESC, SORT_NUMERIC,
                array_column($ARRAY_fencers, "given"), SORT_DESC, SORT_NUMERIC,
                $ARRAY_fencers);
1
Hatem Ben Ammar On
$ratio = [];
$point_difference = [];
$given = [];
foreach($arr as $a){
    $ratio[] = array('id'=>$a['id'],'value'=>$a['ratio']);
    $point_difference[] = array('id'=>$a['id'],'value'=>$a['point_difference']);
    $given[] = array('id'=>$a['id'],'value'=>$a['given']);
}
usort($ratio,"sort_multi");
usort($point_difference,"sort_multi");
usort($given,"sort_multi");
function sort_multi($a, $b){
    if($a['value'] == $b['value']) return 0;
    return ($a['value']<$b['value'])?-1:1;
}