按垂直顺序对多维数组进行排序

I have a multi-dimensional array and I want to sort it. The array looks like this:

$test_arr = [
    /* artist               albums  tracks */
    [ "Green Day",          "8",    "26",   ],
    [ "Remy Zero",          "1",    "2",    ],
    [ "System of a Down",   "1",    "1",    ],
    [ "Modern Talking",     "1",    "1",    ],
    [ "Snow Patrol",        "1",    "2",    ],
    [ "Linkin Park",        "6",    "18",   ],
];

I want to sort the artists with respect to their albums and tracks numbers. To do that, I have created a function.

function sort_mul_dim_arr($mul_dim_arr, $sort_col) {
    $control_arr = [];
    for ($i = 0; $i < count($mul_dim_arr); $i++) {
        array_push($control_arr, $mul_dim_arr[$i][$sort_col]);
    }
    sort($control_arr);
    $sorted_arr = [];
    for ($i = 0; $i < count($control_arr); $i++) {
        for ($j = 0; $j < count($mul_dim_arr); $j++) {
            if ($control_arr[$i] == $mul_dim_arr[$j][$sort_col]) {
                array_push($sorted_arr, $mul_dim_arr[$j]);
            }
        }
    }
    return $sorted_arr;
}

$test_arr = sort_mul_dim_arr($test_arr, 0);

After sorting, the output ($test_arr) would look like this:

$test_arr = [
    /* artist               albums  tracks */
    [ "Green Day",          "8",    "26",   ],
    [ "Linkin Park",        "6",    "18",   ],
    [ "Modern Talking",     "1",    "1",    ],
    [ "Remy Zero",          "1",    "2",    ],
    [ "Snow Patrol",        "1",    "2",    ],
    [ "System of a Down",   "1",    "1",    ],
];

But here's the problem. If the column I use to sort has unique values, function works fine. In the example, artist names are unique. But if I try to use albums or tracks columns to sort, function doesn't work. It messes up the array. Rows start to occur twice or more.

I have read some other questions about sorting multi-dimensional arrays, but they were talking about sorting in horizontal order. I need to sort in vertical order. How can I improve this function so I can sort with non-unique columns too? Or is there a PHP function to that already?

PHP Example

Some variation of this should work (array_column requires PHP >= 5.5.0). Sorts by tracks then albums then artist:

$artist = 0;
$albums = 1;
$tracks = 2;

array_multisort(
    array_column($test_arr, $tracks), SORT_DESC, 
    array_column($test_arr, $albums), SORT_DESC,
    array_column($test_arr, $artist), SORT_DESC,
    $test_arr
);

Here is a function that will do the same:

function sort_one_or_other(&$array, $sort1) {

    $sort2 = ($sort1 = 1) ? 2 : 1;

    array_multisort(
        array_column($array, $sort1), SORT_DESC, 
        array_column($array, $sort2), SORT_DESC,
        array_column($array, 0), SORT_DESC,
        $array
    );
}

sort_one_or_other($test_arr, 2);

print_r($test_arr);

If you really only care about one column with the others unsorted then:

function sort_by_col(&$array, $sort) {    
    array_multisort(array_column($array, $sort), SORT_DESC, $array);
}

sort_by_col($test_arr, 2);

print_r($test_arr);

You can try something like below

$artist = array();$albums = array();$tracks = array();$finalArr = array();
foreach($test_arr as $k=>$v){$artist[] = $v[0];$albums[] = $v[1];$tracks[] = $v[2];}
$length = count($albums);
for($i = 0; $i < $length; $i++){
    for($j = $i + 1; $j < $length; $j++){
        if($albums[$i] < $albums[$j]){
            $temp = $albums[$j]; $tA = $artist[$j]; $tT = $tracks[$j];
            $albums[$j] = $albums[$i]; $artist[$j] = $artist[$i]; $tracks[$j] = $tracks[$i];
            $albums[$i] = $temp; $artist[$i] = $tA; $tracks[$i] = $tT;
        }
    }
}
foreach($albums as $k=>$v){ $finalArr[] = array('artist'=>$artist[$k], 'albums'=>$albums[$k], 'tracks'=>$tracks[$k]);}
print_r($finalArr);

You can use usort(), like that:

<?php

function my_intcmp ($a, $b)
{
    $a = intval ($a);
    $b = intval ($b);
    if ($a == $b) {
        return 0;
    } else {
        return $a < $b ? 1 : -1;
    }
}

function my_sort ($a, $b)
{
    $comp1 = my_intcmp ($a[1], $b[1]);
    if ($comp1) {
        return $comp1;
    } else {
        return my_intcmp ($a[2], $b[2]);
    }
}

usort ($test_arr, "my_sort");
print_r ($test_arr);

?>