phparrayssortingassociative-arrayarray-multisort

PHP array_multisort not sorting with double multidimensional array as expected


Here's my code.

<?php

$data['test1'][0] = array('total' => 67, 'edition' => 2, 'pkg_version' => "2.5.0" );
$data['test1'][1] = array('total' => 67, 'edition' => 2, 'pkg_version' => "0.1.0" );
$data['test1'][2] = array('total' => 67, 'edition' => 2, 'pkg_version' => "0.3.0" );
$data['test2'][0] = array('total' => 86, 'edition' => 1, 'pkg_version' => "1.5.0");
$data['test2'][1] = array('total' => 85, 'edition' => 6, 'pkg_version' => "0.53.0");
$data['test2'][2] = array('total' => 98, 'edition' => 2, 'pkg_version' => "0.3");
$data['test2'][3] = array('total' => 98, 'edition' => 2, 'pkg_version' => "0.2");
$data['test3'][0] = array('total' => 60, 'edition' => 6, 'pkg_version' => "0.3");
$data['test3'][1] = array('total' => 60, 'edition' => 7, 'pkg_version' => "0.1.1");
$data['test3'][2] = array('total' => 60, 'edition' => 7, 'pkg_version' => "0.25");

foreach ($data as $row) {
    foreach ($row as $k){
        foreach ($k as $key => $value){    
            ${$key}[]  = $value; 
        } 
    }
  }

array_multisort($pkg_version, SORT_DESC, $data);

echo "<pre>";
print_r($data);
echo "</pre>";

?>

I am trying to sort a multidimensional array using the array_multisort function

I would like to sort the pkg_version of each element to be ordered

The returned order is not as expected. Not sure, I have misunderstood how

array_multisort works? or my code is wrong. could you guys help me? I try to

solve this problem for a long time. it's quite a complex dimension array.

Here's the result after running the code above.

Array
(
    [test1] => Array
        (
            [0] => Array
                (
                    [total] => 67
                    [edition] => 2
                    [pkg_version] => 2.5.0
                )

            [1] => Array
                (
                    [toal] => 67
                    [edition] => 2
                    [pkg_version] => 0.1.0
                )

            [2] => Array
                (
                    [total] => 67
                    [edition] => 2
                    [pkg_version] => 0.3.0
                )

        )

    [test2] => Array
        (
            [0] => Array
                (
                    [total] => 86
                    [edition] => 1
                    [pkg_version] => 1.5.0
                )

            [1] => Array
                (
                    [total] => 85
                    [type] => 2
                    [pkg_version] => 0.53.0
                )

            [2] => Array
                (
                    [total] => 98
                    [type] => 2
                    [pkg_version] => 0.3
                )

            [3] => Array
                (
                    [total] => 98
                    [edition] => 2
                    [pkg_version] => 0.2
                )

        )

    [test3] => Array
        (
            [0] => Array
                (
                    [total] => 60
                    [edition] => 6
                    [pkg_version] => 0.3
                )

            [1] => Array
                (
                    [total] => 60
                    [edition] => 7
                    [pkg_version] => 0.1.1
                )

            [2] => Array
                (
                    [total] => 60
                    [edition] => 7
                    [pkg_version] => 0.25
                )

        )

)

This is what I expected.

Array
(
    [test1] => Array
        (
            [0] => Array
                (
                    [total] => 67
                    [edition] => 2
                    [pkg_version] => 2.5.0
                )
            [1] => Array
                (
                    [total] => 67
                    [edition] => 2
                    [pkg_version] => 0.3.0
                )
            [2] => Array
                (
                    [toal] => 67
                    [edition] => 2
                    [pkg_version] => 0.1.0
                )
        )

    [test2] => Array
        (
            [0] => Array
                (
                    [total] => 86
                    [edition] => 1
                    [pkg_version] => 1.5.0
                )
            [1] => Array
                (
                    [total] => 85
                    [type] => 2
                    [pkg_version] => 0.53.0
                )
            [2] => Array
                (
                    [total] => 98
                    [type] => 2
                    [pkg_version] => 0.3
                )
            [3] => Array
                (
                    [total] => 98
                    [edition] => 2
                    [pkg_version] => 0.2
                )
        )

    [test3] => Array
        (
            [0] => Array
                (
                    [total] => 60
                    [edition] => 6
                    [pkg_version] => 0.3
                )
            [1] => Array
                (
                    [total] => 60
                    [edition] => 7
                    [pkg_version] => 0.25
                )
            [2] => Array
                (
                    [total] => 60
                    [edition] => 7
                    [pkg_version] => 0.1.1
                )
        )
)


Solution

  • You can loop over the array and use usort()

    <?php
    
    $data['test1'][0] = array('total' => 67, 'edition' => 2, 'pkg_version' => "2.5.0" );
    $data['test1'][1] = array('total' => 67, 'edition' => 2, 'pkg_version' => "0.1.0" );
    $data['test1'][2] = array('total' => 67, 'edition' => 2, 'pkg_version' => "0.3.0" );
    $data['test2'][0] = array('total' => 86, 'edition' => 1, 'pkg_version' => "1.5.0");
    $data['test2'][1] = array('total' => 85, 'edition' => 6, 'pkg_version' => "0.53.0");
    $data['test2'][2] = array('total' => 98, 'edition' => 2, 'pkg_version' => "0.3");
    $data['test2'][3] = array('total' => 98, 'edition' => 2, 'pkg_version' => "0.2");
    $data['test3'][0] = array('total' => 60, 'edition' => 6, 'pkg_version' => "0.3");
    $data['test3'][1] = array('total' => 60, 'edition' => 7, 'pkg_version' => "0.1.1");
    $data['test3'][2] = array('total' => 60, 'edition' => 7, 'pkg_version' => "0.25");
    
    // use a reference to the sub array
    //                |
    //                |
    //                v
    foreach ($data as &$row)
    {
        usort($row, function($a, $b)
                    {
                        // make a desc sort by comparing $b against $a instead of $a against $b
                        return strcmp($b['pkg_version'], $a['pkg_version']);
                    });
    }
    
    var_dump($data);
    

    This outputs :

    array(3) {
      ["test1"]=>
      array(3) {
        [0]=>
        array(3) {
          ["total"]=>
          int(67)
          ["edition"]=>
          int(2)
          ["pkg_version"]=>
          string(5) "2.5.0"
        }
        [1]=>
        array(3) {
          ["total"]=>
          int(67)
          ["edition"]=>
          int(2)
          ["pkg_version"]=>
          string(5) "0.3.0"
        }
        [2]=>
        array(3) {
          ["total"]=>
          int(67)
          ["edition"]=>
          int(2)
          ["pkg_version"]=>
          string(5) "0.1.0"
        }
      }
      ["test2"]=>
      array(4) {
        [0]=>
        array(3) {
          ["total"]=>
          int(86)
          ["edition"]=>
          int(1)
          ["pkg_version"]=>
          string(5) "1.5.0"
        }
        [1]=>
        array(3) {
          ["total"]=>
          int(85)
          ["edition"]=>
          int(6)
          ["pkg_version"]=>
          string(6) "0.53.0"
        }
        [2]=>
        array(3) {
          ["total"]=>
          int(98)
          ["edition"]=>
          int(2)
          ["pkg_version"]=>
          string(3) "0.3"
        }
        [3]=>
        array(3) {
          ["total"]=>
          int(98)
          ["edition"]=>
          int(2)
          ["pkg_version"]=>
          string(3) "0.2"
        }
      }
      ["test3"]=>
      &array(3) {
        [0]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(6)
          ["pkg_version"]=>
          string(3) "0.3"
        }
        [1]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(7)
          ["pkg_version"]=>
          string(4) "0.25"
        }
        [2]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(7)
          ["pkg_version"]=>
          string(5) "0.1.1"
        }
      }
    }
    

    Note that in the last array, the version 0.3 is higher than the version 0.25. Since it's the order in your expected output, I left it as is, but if not, you can use instead of strcmp(), version_compare(), this will provide this output for $data['test3'] :

      ["test3"]=>
      &array(3) {
        [0]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(7)
          ["pkg_version"]=>
          string(4) "0.25"
        }
        [1]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(6)
          ["pkg_version"]=>
          string(3) "0.3"
        }
        [2]=>
        array(3) {
          ["total"]=>
          int(60)
          ["edition"]=>
          int(7)
          ["pkg_version"]=>
          string(5) "0.1.1"
        }
      }
    }