-2

I'm trying to order this multidimensional array, with no success. I need to sort ascending by pub_obs but keeping the main array order (AC, BA, ..). The indexes inside the main arrays (0, 1, 2, ..) can change but the pub_id have to be the same.

Array(
    [AC] => Array
        (
            [0] => Array
                (
                    [pub_id] => 1
                    [pub_obs] => c
                )
            [1] => Array
                (
                    [pub_id] => 3
                    [pub_obs] => a
                )
            [2] => Array
                (
                    [pub_id] => 4
                    [pub_obs] => c
                )
        )
    [BA] => Array
        (
            [0] => Array
                (
                    [pub_id] => 1
                    [pub_obs] => b
                )
            [1] => Array
                (
                    [pub_id] => 2
                    [pub_obs] => b
                )
            [2] => Array
                (
                    [pub_id] => 7
                    [pub_obs] => a
                )
        )
)

Somebody can help? Thanks!

Edit

I forgot to say about the PHP version, 5.2, but @fusion3k was quick! thanks for the answer dude and for everybody who helped too!

2 Answers2

0

Use a foreach with main array by reference, then usort fore each row:

foreach( $array as &$row )
{
    usort
    (
        $row,
        function( $a, $b )
        {
            return strcmp($a['pub_obs'], $b['pub_obs']);
        }
    );
}

Output:

Array
(
    [AC] => Array
        (
            [0] => Array
                (
                    [pub_id] => 3
                    [pub_obs] => a
                )

            [1] => Array
                (
                    [pub_id] => 4
                    [pub_obs] => c
                )

            [2] => Array
                (
                    [pub_id] => 1
                    [pub_obs] => c
                )

        )

    [BA] => Array
        (
            [0] => Array
                (
                    [pub_id] => 7
                    [pub_obs] => a
                )

            [1] => Array
                (
                    [pub_id] => 2
                    [pub_obs] => b
                )

            [2] => Array
                (
                    [pub_id] => 1
                    [pub_obs] => b
                )

        )

)

Using references in the foreach the usort function act directly on main array, then in custom function compare pub_id keys to define nested sort order.

Edit:

The above method works, as requested in the question. However, if we have a sub-array like this one:

[
    [ 'pub_id' => 1, 'pub_obs' => 'b' ],
    [ 'pub_id' => 2, 'pub_obs' => 'b' ],
    [ 'pub_id' => 3, 'pub_obs' => 'a' ]
]

the output is:

Array
(
    [0] => Array
        (
            [pub_id] => 3
            [pub_obs] => a
        )
    [1] => Array
        (
            [pub_id] => 2
            [pub_obs] => b
        )
    [2] => Array
        (
            [pub_id] => 1
            [pub_obs] => b
        )
)

The requested keys are correctly sorted, but — on same pub_obs value — pub_id order is not maintained.

To avoid this, you have to sub-process even the pub_id key:

    usort
    (
        $row,
        function( $a, $b )
        {

            $mainCmp = strcmp( $a['pub_obs'], $b['pub_obs'] );
            if( !$mainCmp )
            {
                return( strcmp( $a['pub_id'], $b['pub_id'] ) );
            }
            else return $mainCmp;
        }
    );

Using this solution in PHP < 5.3

Simply define a custom function with same content of above anonymous function:

function myCompare( $a, $b )
{

    $mainCmp = strcmp( $a['pub_obs'], $b['pub_obs'] );
    if( !$mainCmp )
    {
        return( strcmp( $a['pub_id'], $b['pub_id'] ) );
    }
    else 
    return $mainCmp;
}

and then call it inside the foreach() loop:

foreach( $array as &$row )
{
    usort( $row, 'myCompare' );
}

demo



PS: Thank you to @deceze for previous edit (maintained here).

fusion3k
  • 11,568
  • 4
  • 25
  • 47
-1

You can use the aasort from this answer: Sort Multi-dimensional Array by Value and apply it to each array row:

function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii]=$va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii]=$array[$ii];
    }
    $array=$ret;
}
 //Now your array
 foreach($array as $key => &$value){
   aasort($value,"pub_obs");
 }
Community
  • 1
  • 1