note 35230 added to function.array-multisort
| From: | oliver at realtsp dot com | Date: | Sun, 24 Aug 2003 12:33:19 +0000 |
| Subject: | note 35230 added to function.array-multisort | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-54988@lists.php.net to get a copy of this message | ||
More on sorting arrays of "rows", by their columns:
Building on the ideas of "Ichier" and "steve at mg-rover dot org" below, I have
combined this into a function which will sort a 2-dimensional array (ie an array of rows) by its
columns. Unlike Ichiers function it will preserve the keys of the rows by using Steve's
"_" trick.
I first tried to achieve the column sort with a
"transpose->array_multisort->transpose" approach, but then realiased that
Ichier's code was better, because it saves the second transpose (thanks Ichier).
The new fucntion (which I have named array_column_sort() to be more within the php convention) works
well, but has the following disadvantage still.
It requires making 2 copies of your original array:
- one copy within the function to do the "_" prefixing which saves the keys. If anyone
knows how to modify all the keys in an array of arrays without making a copy of it, let me know.
This copy of the original array is temporary because it is local to the function.
- Plus a second copy because the function (unlike array_multisort) doesn't operate on the array
you pass it, but returns a new array. This is because Ichiers code uses func_get_args() to keep the
syntax of the function flexible and func_get_args() doesn't handle, passing by reference. If
anyone can think of a way around this also let me know.
This should definitely be a standard php function, because this is a very common problem, since db
results always come in this form.
Here is the code for the new array_column_sort function:
<?php
/**
* array_column_sort
*
* function to sort an "arrow of rows" by its columns
* exracts the columns to be sorted and then
* uses eval to flexibly apply the standard
* array_multisort function
*
* uses a temporary copy of the array whith "_" prefixed to the keys
* this makes sure that array_multisort is working with an associative
* array with string type keys, which in turn ensures that the keys
* will be preserved.
*
* TODO: find a way of modifying the keys of $array directly, without using
* a copy of the array.
*
* flexible syntax:
* $new_array = array_column_sort($array [, 'col1' [, SORT_FLAG [, SORT_FLAG]]]...);
*
* original code credited to Ichier (www.ichier.de) here:
* http://uk.php.net/manual/en/function.array-multisort.php
*
* prefixing array indeces with "_" idea credit to steve at mg-rover dot org, also here:
* http://uk.php.net/manual/en/function.array-multisort.php
*
*/
function array_column_sort()
{
$args = func_get_args();
$array = array_shift($args);
// make a temporary copy of array for which will fix the
// keys to be strings, so that array_multisort() doesn't
// destroy them
$array_mod = array();
foreach ($array as $key => $value)
$array_mod['_' . $key] = $value;
$i = 0;
$multi_sort_line = "return array_multisort( ";
foreach ($args as $arg)
{
$i++;
if ( is_string($arg) )
{
foreach ($array_mod as $row_key => $row)
{
$sort_array[$i][] = $row[$arg];
}
}
else
{
$sort_array[$i] = $arg;
}
$multi_sort_line .= "\$sort_array[" . $i . "], ";
}
$multi_sort_line .= "\$array_mod );";
eval($multi_sort_line);
// now copy $array_mod back into $array, stripping off the "_"
// that we added earlier.
$array = array();
foreach ($array_mod as $key => $value)
$array[ substr($key, 1) ] = $value;
return $array;
}
?>
Hope it helps, and maybe gets included in a future php version.
Oliver
----
Manual Page -- http://www.php.net/manual/en/function.array-multisort.php
Edit Note -- http://master.php.net/manage/user-notes.php?action=edit+35230
Delete Note -- http://master.php.net/manage/user-notes.php?action=delete+35230&report=yes
Reject Note -- http://master.php.net/manage/user-notes.php?action=reject+35230&report=yes