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