Rate this script:  I Love it  /   I Hate it

Sort multiple dimensional arrays by column without the need to extract the column data first.


Code


<?php
/*
(C) UK 2006 Richard Quadling

This work is licensed under the Creative Commons Attribution 2.5 License.
To view a copy of this license, visit http://creativecommons.org/licenses/by/2.5/ or send a letter to
    Creative Commons,
    543 Howard Street,
    5th Floor,
    San Francisco,
    California,
    94105, USA.

Version History

2006/09/20
Removed reliance on PHP's constants as using column numbers conflicted with these constants.
Use AMC_SORT_xxx rather than SORT_xxx.

2006/08/23
Added CC license
Added notice and error for parameters

2006/08/22
Fixed local defines to be well out of the way of the ones used by PHP.

2006/08/07
Created this code based upon work done by KES (http://www.php.net/manual/en/function.array-multisort.php#68452)
*/


// AMC defines for keeping association.
define ('AMC_LOSE_ASSOCIATION', 'AMC10001');
define ('AMC_KEEP_ASSOCIATION', 'AMC10002');

// AMC defines for the global array.
define ('AMC_SORT_ORDER', 'AMC10003');
define ('AMC_SORT_TYPE', 'AMC10004');

// AMC defines for the sort order.
define ('AMC_SORT_ASC', 'AMC10005');
define ('AMC_SORT_DESC', 'AMC10006');

// AMC defines for sorting type.
define ('AMC_SORT_REGULAR', 'AMC10007');
define ('AMC_SORT_NUMERIC', 'AMC10008');
define ('AMC_SORT_STRING', 'AMC10009');
define ('AMC_SORT_STRING_CASELESS', 'AMC10010');

/**
  * bool array_multisort_column ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )
  **/

function array_multisort_column(array &$a_data, $m_mixed1)
    {
    // Get the parameters and the number of parameters.
    $a_Args = func_get_args();
    $i_Args = func_num_args();

    // Define a global empty array for the comparison function.
    $GLOBALS['a_AMC_ordering'] = array();

    // Get the list of columns.
    $a_Columns = array_keys(reset($a_data));

    // Assume association is NOT kept
    $b_KeepAssociation = False;

    // Process the parameter list, extracting columns and any applicable settings.
    for($i_Arg = 1 ; $i_Arg < $i_Args ; )
        {
        // Initially we only want to look at columns.
        if (in_array($a_Args[$i_Arg], $a_Columns))
            {
            // Track the column.
            $s_Column = $a_Args[$i_Arg];

            // Add the column with default settings to the global array.
            $GLOBALS['a_AMC_ordering'][$a_Args[$i_Arg]] = array
                (
                AMC_SORT_ORDER => AMC_SORT_ASC,
                AMC_SORT_TYPE => AMC_SORT_REGULAR,
                );

            // While there are more parameters to process is the next one a controller rather than a column.
            while
                (

                // There IS a next parameter.
                isset($a_Args[$i_Arg + 1]) &&

                // It is a controller.
                in_array
                    (
                    $a_Args[$i_Arg + 1],
                    array
                        (
                        AMC_KEEP_ASSOCIATION,
                        AMC_LOSE_ASSOCIATION,
                        AMC_SORT_STRING_CASELESS,
                        AMC_SORT_ASC,
                        AMC_SORT_DESC,
                        AMC_SORT_NUMERIC,
                        AMC_SORT_REGULAR,
                        AMC_SORT_STRING,
                        ),
                    True
                    )

                )
                {
                // Deal with column sorting order.
                if (
                    in_array
                        (
                        $a_Args[$i_Arg + 1],
                        array
                            (
                            AMC_SORT_ASC,
                            AMC_SORT_DESC
                            ),
                        True
                        )
                    )
                    {
                    $GLOBALS['a_AMC_ordering'][$s_Column][AMC_SORT_ORDER] = $a_Args[$i_Arg + 1];
                    }
                // Deal with column sorting type.
                elseif (
                    in_array
                        (
                        $a_Args[$i_Arg + 1],
                        array
                            (
                            AMC_SORT_REGULAR,
                            AMC_SORT_NUMERIC,
                            AMC_SORT_STRING,
                            AMC_SORT_STRING_CASELESS
                            ),
                        True
                        )
                    )
                    {
                    $GLOBALS['a_AMC_ordering'][$s_Column][AMC_SORT_TYPE] = $a_Args[$i_Arg + 1];
                    }
                // Deal with array association.
                else
                    {
                    $b_KeepAssociation = (AMC_KEEP_ASSOCIATION == $a_Args[$i_Arg + 1]);
                    }
                // Take the next argument out of the picture.
                ++$i_Arg;
                }
            }
        // Allow array association to be defined.
        elseif (
            in_array
                (
                $a_Args[$i_Arg],
                array
                    (
                    AMC_KEEP_ASSOCIATION,
                    AMC_LOSE_ASSOCIATION
                    ),
                True
                )
            )
            {
            $b_KeepAssociation = (AMC_KEEP_ASSOCIATION == $a_Args[$i_Arg]);
            }
        // Ignore sort options as they are not in the right place to be understood.
        elseif (
            in_array
                (
                $a_Args[$i_Arg],
                array
                    (
                    AMC_SORT_REGULAR,
                    AMC_SORT_NUMERIC,
                    AMC_SORT_STRING,
                    AMC_SORT_STRING_CASELESS
                    ),
                True
                )
            )
            {
            trigger_error("Parameter $i_Arg of '{$a_Args[$i_Arg]}' is not applicable and has been ignored.", E_USER_NOTICE);
            }
        // Whatever is left is an error.
        else
            {
            trigger_error("Requested column of '{$a_Args[$i_Arg]}' is not present in the supplied array.", E_USER_ERROR);
            }
        // Get the next argument.
        ++$i_Arg;
        }

    // Determine which usort mechanism (with or without associations).
    $s_Sorter = ($b_KeepAssociation ? 'uasort' : 'usort');

    // Sort the data and get the result.
    $b_Result = $s_Sorter($a_data, 'array_multisort_column_cmp');

    // Remove the temporary global array.
    unset($GLOBALS['a_AMC_ordering']);

    // Return the results
    return $b_Result;
    }

/**
  * int array_multisort_column_cmp(array a_left, array a_right)
  **/

function array_multisort_column_cmp(array &$a_left, array &$a_right)
    {
    // Assume that the entries are the same.
    $i_Result = 0;

    // Process each column defined in the global array.
    foreach($GLOBALS['a_AMC_ordering'] as $s_Column => $a_ColumnData)
        {
        // Handle the different sort types.
        switch ($a_ColumnData[AMC_SORT_TYPE])
            {
            // Numeric.
            case AMC_SORT_NUMERIC :
                $i_ColumnCompareResult =
                    ((intval($a_left[$s_Column]) == intval($a_right[$s_Column]))
                    ?
                        0
                    :
                        ((intval($a_left[$s_Column]) < intval($a_right[$s_Column]))
                        ?
                            -1
                        :
                            1
                        )
                    );
                break;
            // Case sensitive strings.
            case AMC_SORT_STRING :
                $i_ColumnCompareResult = strcmp((string)$a_left[$s_Column], (string)$a_right[$s_Column]);
                break;
            // Case insensitive strings.
            case AMC_SORT_STRING_CASELESS :
                $i_ColumnCompareResult = strcasecmp((string)$a_left[$s_Column], (string)$a_right[$s_Column]);
                break;
            // Regular sorting.
            case AMC_SORT_REGULAR :
            default :
                $i_ColumnCompareResult =
                    (($a_left[$s_Column] == $a_right[$s_Column])
                    ?
                        0
                    :
                        (($a_left[$s_Column] < $a_right[$s_Column])
                        ?
                            -1
                        :
                            1
                        )
                    );
                break;
            }
        // Is the column in the two arrays the same?
        if (0 == $i_ColumnCompareResult)
            {
            // Continue with the next column.
            continue;
            }
        // Are we sorting descending?
        $i_Result = $i_ColumnCompareResult * (($a_ColumnData[AMC_SORT_ORDER] == AMC_SORT_DESC) ? -1 : 1);

        // As there is a difference, we do not need to continue with the remaining columns.
        break;
        }

    // Return the result.
    return $i_Result;
    }
?>

 

 
Sort multiple dimensional arrays by column without the need to extract the column data first. scripts | Sort multiple dimensional arrays by column without the need to extract the column data first. snippet | Sort multiple dimensional arrays by column without the need to extract the column data first. example | Sort multiple dimensional arrays by column without the need to extract the column data first. tutorial | Sort multiple dimensional arrays by column without the need to extract the column data first. code