0

I try to sort a multidimensional array in the way, so that the elements with the same value should not being reordered.

This is the given array, which should be sorted by the value of type:

$arr = array(

    "a" => array(
        "type" => 1
    ),
    "d" => array(
        "type" => 1
    ),
    "super" => array(
        "type" => 2
    ),
    "c" => array(
        "type" => 1
    ),
    "b" => array(
        "type" => 1
    )

);

The sorted array should be look like this:

Array
(
    [super] => Array
        (
            [type] => 2
        )

    [a] => Array
        (
            [type] => 1
        )

    [d] => Array
        (
            [type] => 1
        )

    [c] => Array
        (
            [type] => 1
        )

    [b] => Array
        (
            [type] => 1
        )

)
Karsten
  • 313
  • 4
  • 12

3 Answers3

0

Try a uasort: If you are still on PHP 5.2 or earlier, you'll have to define a sorting function first:

$myArray = array(

    "a" => array(
        "type" => 1
    ),
    "d" => array(
        "type" => 1
    ),
    "super" => array(
        "type" => 2
    ),
    "c" => array(
        "type" => 1
    ),
    "b" => array(
        "type" => 1
    )

);
function sortByOrder($a, $b)
{
    return $b['type'] - $a['type'];
}

uasort($myArray, 'sortByOrder');
print_r($myArray);

Starting in PHP 5.3, you can use an anonymous function:

uasort($myArray, function ($a, $b) {
    return $b['type'] - $a['type'];
});

And finally with PHP 7 you can use the "spaceship operator":

uasort($myArray, function ($a, $b) {
        return $b['type'] <=> $a['type'];
});

Output:

Array
(
    [super] => Array
        (
            [type] => 2
        )

    [b] => Array
        (
            [type] => 1
        )

    [c] => Array
        (
            [type] => 1
        )

    [a] => Array
        (
            [type] => 1
        )

    [d] => Array
        (
            [type] => 1
        )

)
Chetan Ameta
  • 7,303
  • 2
  • 28
  • 44
  • Thanks for your answer, but the output is not that what I want: The difference is, that I want to keep the order of the elements with the same type. – Karsten Feb 18 '16 at 11:12
0

After browsing through the post (How can I sort arrays and data in PHP?)[How can I sort arrays and data in PHP?, I found a solution for my problem.

If the types are equal, I sort the elements into a static order, which I get from a second value id.

Array to sort:

$array = array(

    "a" => array(
        "id" => "a",
        "type" => 1
    ),
    "c" => array(
        "id" => "c",
        "type" => 1
    ),
    "super" => array(
        "id" => "super",
        "type" => 2
    ),
    "b" => array(
        "id" => "b",
        "type" => 1
    )

);

Script:

$sort_keys = array_column($array, "id");

function cmp($a, $b){

    global $sort_keys;

    if ($a["type"] < $b["type"]) {
        return 1;
    } else if ($a["type"] > $b["type"]) {
        return -1;
    } else {
        return array_search($a["_id"], $sort_keys) - array_search($b["_id"], $sort_keys);
    }

}

uasort($array, 'cmp');

I do have the field id in my script already, so I don’t even have to change my array.

Thanks to all who contribute to this post!

Community
  • 1
  • 1
Karsten
  • 313
  • 4
  • 12
0

I want to improve your own answer to exclude inefficient array_search(). It is better to index array items before sorting, and use it for equal types.

$index = 0;
foreach ($arr as $key => $value) {
  $arr[$key]['index'] = $index;
  $index++;
}

uasort($arr, function($a, $b) {
  if ($a['type'] < $b['type']) {
    return 1;
  } elseif ($a['type'] > $b['type']) {
    return -1;
  } else {
    return $a['index'] - $b['index'];
  }
});

foreach ($arr as $key => $value) {
  unset($arr[$key]['index']);
}
Max Zuber
  • 1,166
  • 9
  • 15
  • Thanks for that – I now use your solution. The only thing I had to add, was a additional `foreach` loop to remove `'index'` after sorting. Maybe you can update your answer to reflect this. – Karsten Feb 22 '16 at 12:32