Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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

share|improve this question

3 Answers 3

up vote 1 down vote accepted

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);
share|improve this answer
    
Is there a way to wrap this in a function and pass the column index to it? For example: sort_arr($main_arr, 0), 0 being the index for artists, 1 being the index for albums etc. I need a function to do sorting, because the sort order won't be fixed. I'll change it on the fly with JS. Since I'm not familiar with array_multisort and array_column, I don't know where to begin. –  akinuri Aug 13 '14 at 18:09
    
You state you want to sort by albums and tracks but you only want to pass one column into the function? How is that? –  AbraCadaver Aug 13 '14 at 18:12
    
I want to pass a column index to a function that will sort the array by that index (column values) while keeping the the cells of the rows intact. In the example I gave in my question, the function I created does that. I pass an array and a column index. I have a table in my page and I'll be sorting the columns with clicks to table headers. The only thing that will be changing is the column I select to sort the array. –  akinuri Aug 13 '14 at 18:24
    
One of the two in the edit should do it. –  AbraCadaver Aug 13 '14 at 18:27
    
sort_by_col did the trick. Used SORT_ASC instead of SORT_DESC. Didn't need to sort the other columns since they sort ascending by default, which is what I'm using to sort. Thank you. This was very educational. –  akinuri Aug 13 '14 at 19:33

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);
share|improve this answer

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

?>
share|improve this answer

Your Answer

 
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.