note 95543 deleted from function.array-multisort by danbrown
| From: | danbrown@php.net | Date: | Fri, 08 Jan 2010 15:17:34 +0000 |
| Subject: | note 95543 deleted from function.array-multisort by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-164790@lists.php.net to get a copy of this message | ||
Note Submitter: cagret at gmail dot com
----
d_inkubus at yahoo dot com 21-Dec-2009 11:33:
There is a bug in your update to array_msort():
<?php
foreach($order as $order_element) {
$params[]=&$order_element;
}
?>
You are making a reference to a local loop variable that will change through the loop.
It's going to work ok when you sort only by 1 column:
<?php
$refs = array_msort($refs, array('hits'=>SORT_DESC));
?>
>>$order_element == SORT_DESC
But when you sort by multiple columns:
<?php
$refs = array_msort($refs, array('hits'=>SORT_DESC, 'uri'=>SORT_ASC,
'from'=>SORT_ASC));
?>
>>hits $order_element == SORT_ASC, uri $order_element == SORT_ASC, from $order_element ==
>>SORT_ASC
It even gets more complicated if you provide more flags.
After foreach is executed $order_element contains the last value, seems like this will solve the
problem:
<?php
foreach($order as $k => $order_element) {
$params[] =& $order[$k];
}
?>
But no, because that loop is inside another loop, so $order is also a local loop variable.
The solution:
<?php
foreach ($cols as $col => $order) {
$params[] =& $colarr[$col];
$cols[$col] = (array) $cols[$col];
foreach ($cols[$col] as $k => $ordval) {
$params[] =& $cols[$col][$k];
}
}
?>
The final version of array_msort:
<?php
function array_msort($array, $cols)
{
// Example: $arr2 = array_msort($arr1, array('name'=>array(SORT_ASC,SORT_REGULAR),
'cat'=>SORT_DESC));
$colarr = array();
foreach ($cols as $col => $order) {
$colarr[$col] = array();
foreach ($array as $k => $row) {
$colarr[$col]['_'.$k] = strtolower($row[$col]);
}
}
$params = array();
foreach ($cols as $col => $order) {
$params[] =& $colarr[$col];
$cols[$col] = (array) $cols[$col];
foreach ($cols[$col] as $k => $ordval) {
$params[] =& $cols[$col][$k];
}
}
call_user_func_array('array_multisort', $params);
$ret = array();
$keys = array();
$first = true;
foreach ($colarr as $col => $arr) {
foreach ($arr as $k => $v) {
if ($first) {
$keys[$k] = substr($k, 1);
}
$k = $keys[$k];
if (!isset($ret[$k])) {
$ret[$k] = $array[$k];
}
$ret[$k][$col] = $array[$k][$col];
}
$first = false;
}
return $ret;
}
?>