Sort multiple dimensional arrays by column without the need to extract the column data first.
The syntax is the same as array_multisort().
You also have 3 additional parameters you can use:
AMC_SORT_STRING_CASELESS to sort the strings case insensitively.
AMC_LOSE_ASSOCIATION (the default behaviour) to lose the associations for the array.
AMC_KEEP_ASSOCIATION to keep the associations for the array.
If your array does not have associated indexes, then you can use column numbers. But watch out. If you also use PHP's constants like SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC or SORT_STRING, then these can be mixed up with column numbers.
So, to remove this problem, I've created copies of these constants:
AMC_SORT_ASC
AMC_SORT_DESC
AMC_SORT_REGULAR
AMC_SORT_NUMERIC
AMC_SORT_STRING
Other than that, these function work together JUST like array_multisort but sorts using column(s) without the need to first extract the columns into individual arrays.
<?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; } ?>