phpsortingmultidimensional-arraygroupingarray-multisort

Sort array rows by one column in tiers of 10, then by another column


How to do 2-tier sorting on an array using below criteria:

edd value groups:

  1. 1-10
  2. 11-20
  3. 21-30

The array is

$var_array = [
    ['name' => 'product1', 'edd'=>16, 'price' => 89],
    ['name' => 'product2', 'edd'=>21, 'price' => 99],
    ['name' => 'product3', 'edd'=>2, 'price' => 110],
    ['name' => 'product4', 'edd'=>14, 'price' => 102],
    ['name' => 'product5', 'edd'=>8, 'price' => 119],
    ['name' => 'product6', 'edd'=>6, 'price' => 123],
    ['name' => 'product7', 'edd'=>26, 'price' => 93],
    ['name' => 'product8', 'edd'=>27, 'price' => 105],
    ['name' => 'product9', 'edd'=>18, 'price' => 133],
];

First sort the edd, and then sort the price within each edd group level.

Expected result

$var_array = [
    ['name' => 'product3', 'edd' => 2, 'price' => 110],
    ['name' => 'product5', 'edd' => 8, 'price' => 119],
    ['name' => 'product6', 'edd' => 6, 'price' => 123],

    ['name' => 'product1', 'edd' => 16, 'price' => 89],
    ['name' => 'product4', 'edd' => 14, 'price' => 102],
    ['name' => 'product9', 'edd' => 18, 'price' => 133],

    ['name' => 'product7', 'edd' => 26, 'price' => 93],
    ['name' => 'product2', 'edd' => 21, 'price' => 99],
    ['name' => 'product8', 'edd' => 27, 'price' => 105],
];

Solution

  • You can use array_reduce and array_map

    $var_array = array(
        array('name' => 'product1', 'edd'=>16, 'price' => 89),
        array('name' => 'product2', 'edd'=>21, 'price' => 99),
        array('name' => 'product3', 'edd'=>2, 'price' => 110),
        array('name' => 'product4', 'edd'=>14, 'price' => 102),
        array('name' => 'product5', 'edd'=>8, 'price' => 119),
        array('name' => 'product6', 'edd'=>6, 'price' => 123),
        array('name' => 'product7', 'edd'=>26, 'price' => 93),
        array('name' => 'product8', 'edd'=>27, 'price' => 105),
        array('name' => 'product9', 'edd'=>18, 'price' => 133),
    );
    
    //Group array and sort key
    $temp = array_reduce($var_array, function($c, $v){
        $c[ ceil($v["edd"] / 10) * 10 ][] = $v;
        return $c;
    }, array());
    
    ksort($temp);
    
    //Sort array
    $temp = array_map(function ($n) {
        usort($n, function($a, $b){
                return $a["price"] - $b["price"];
            });
        return $n;
    }, $temp );
    
    
    //Make 2 dimentional array into 1
    $result = array_reduce($temp, 'array_merge', array());
    
    echo "<pre>";
    print_r( $result );
    echo "</pre>";
    

    This will result to:

    Array
    (
        [0] => Array
            (
                [name] => product3
                [edd] => 2
                [price] => 110
            )
    
        [1] => Array
            (
                [name] => product5
                [edd] => 8
                [price] => 119
            )
    
        [2] => Array
            (
                [name] => product6
                [edd] => 6
                [price] => 123
            )
    
        [3] => Array
            (
                [name] => product1
                [edd] => 16
                [price] => 89
            )
    
        [4] => Array
            (
                [name] => product4
                [edd] => 14
                [price] => 102
            )
    
        [5] => Array
            (
                [name] => product9
                [edd] => 18
                [price] => 133
            )
    
        [6] => Array
            (
                [name] => product7
                [edd] => 26
                [price] => 93
            )
    
        [7] => Array
            (
                [name] => product2
                [edd] => 21
                [price] => 99
            )
    
        [8] => Array
            (
                [name] => product8
                [edd] => 27
                [price] => 105
            )
    
    )