#6344: msort function added to the Set class to help with array sorting using
multiple column parameters
--------------------------+-------------------------------------------------
Reporter: ebadedude | Type: Enhancement
Status: new | Priority: Medium
Milestone: 1.3.x.x | Component: Core Libs
Version: 1.2 Final | Severity: Normal
Keywords: | Php_version: n/a
Cake_version: |
--------------------------+-------------------------------------------------
I needed the ability to sort an array using multiple columns criteria. the
Set class has a "sort" function but it only takes one "$path/$dir"
criterion. "msort" takes an array of "$path/$dir" criteria. I am not sure
about the usefulness of this functionality, but I felt I should share.
Also, the code could be enhanced upon as this is the first version.
Set Class Addition:
{{{
/**
* NOTE: similar to sort but returns two arrays
* Sorts an array by any value, determined by a Set-compatible path
*
* @param array $data
* @param string $path A Set-compatible path to the array value
* @param string $dir asc/desc
* @return array [sorted] - Sorted Array
* [section] - Sorted Array seperated by
similar groupings
* @static
*/
function sort2($data, $path, $dir) {
$sortedSections = array();
$result = Set::__flatten(Set::extract($data, $path));
list($keys, $values) = array(Set::extract($result,
'{n}.id'), Set::extract($result, '{n}.value'));
$dir = strtolower($dir);
if ($dir === 'asc') {
$dir = SORT_ASC;
} elseif ($dir === 'desc') {
$dir = SORT_DESC;
}
array_multisort($values, $dir, $keys, $dir);
$sorted = array();
$keys = array_unique($keys);
$sectArr = array(); //Store sorted section
groupings
$prevVal = ''; //Used for comparison
$count = 0;
foreach ($keys as $k) {
if($count == 0) {
$sectArr[] = $data[$k];
$prevVal = $values[$count];
} else {
if($prevVal == $values[$count]) {
$sectArr[] = $data[$k];
} else {
$sortedSections[] = $sectArr;
$sectArr = array();
$sectArr[] = $data[$k];
}
$prevVal = $values[$count];
}
$sorted[] = $data[$k];
$count++;
}
$sortedSections[] = $sectArr;
return array('sorted' => $sorted, 'sectioned' =>
$sortedSections);
}
/**
* Sorts an array by an array of multiple values, determined by a Set-
compatible path
* Similar to sort but takes an array of $path and $dir instead of single
values
* Usage example -> Set::msort($data,
array('{n}.vname'=>'DESC','{n}.pname'=>'DESC'))
*
* @param array $data
* @param array $patharr An array of Set-compatible path to the array
value
* @return array
* @static
*/
function msort($data, $patharr) {
$sorted = $data;
if(!is_array($patharr))
return $sorted;
$sortedSectArr = array($data);
foreach($patharr as $path => $dir) {
$tmpSorted = array(); //Stores
temporary list of sorted array
$tmpSectionSorted = array(); //Stores temporary
list of sorted array grouped by current sorting path
foreach($sortedSectArr as $data2) {
$res = Set::sort2($data2, $path, $dir);
$tmpSorted[] = $res['sorted'];
$tmpSectionSorted[] = $res['sectioned'];
}
//Generate new sorted list
$sorted = array();
foreach($tmpSorted as $sortedArr) {
foreach($sortedArr as $sorted2) {
$sorted[] = $sorted2;
}
}
$sortedSectArr = array();
foreach($tmpSectionSorted as $sectionLvl) {
foreach($sectionLvl as $sectionLvl2) {
$sortedSectArr[] = $sectionLvl2;
}
}
}
return $sorted;
}
}}}
Usage (In Controller):
{{{
$data = Array(
Array(
'vid' => 1,
'vname' => 'Test Entry V1',
'pid' => 1,
'pname' => 'Test Entry P1',
'yid' => 1,
'yname' => 'Test Entry Y1'
),
Array(
'vid' => 2,
'vname' => 'Test Entry V2',
'pid' => 2,
'pname' => 'Test Entry P0',
'yid' => 2,
'yname' => 'Test Entry Y2'
),
Array(
'vid' => 3,
'vname' => 'Test Entry V1',
'pid' => 3,
'pname' => 'Test Entry P2',
'yid' => 2,
'yname' => 'Test Entry Y2'
)
);
$res1 = Set::msort($data,array('{n}.vname'=>'DESC','{n}.pname'=>'DESC'));
$res2 = Set::msort($data,array('{n}.vname'=>'DESC','{n}.pname'=>'ASC'));
//Result
$res1 = Array
(
[0] => Array
(
[vid] => 2
[vname] => Test Entry V2
[pid] => 2
[pname] => Test Entry P0
[yid] => 2
[yname] => Test Entry Y2
)
[1] => Array
(
[vid] => 3
[vname] => Test Entry V1
[pid] => 3
[pname] => Test Entry P2
[yid] => 2
[yname] => Test Entry Y2
)
[2] => Array
(
[vid] => 1
[vname] => Test Entry V1
[pid] => 1
[pname] => Test Entry P1
[yid] => 1
[yname] => Test Entry Y1
)
)
$res2 = Array
(
[0] => Array
(
[vid] => 2
[vname] => Test Entry V2
[pid] => 2
[pname] => Test Entry P0
[yid] => 2
[yname] => Test Entry Y2
)
[1] => Array
(
[vid] => 1
[vname] => Test Entry V1
[pid] => 1
[pname] => Test Entry P1
[yid] => 1
[yname] => Test Entry Y1
)
[2] => Array
(
[vid] => 3
[vname] => Test Entry V1
[pid] => 3
[pname] => Test Entry P2
[yid] => 2
[yname] => Test Entry Y2
)
)
}}}
--
Ticket URL: <https://trac.cakephp.org/ticket/6344>
CakePHP : The Rapid Development Framework for PHP <https://trac.cakephp.org/>
Cake is a rapid development framework for PHP which uses commonly known design
patterns like ActiveRecord, Association Data Mapping, Front Controller and MVC.
Our primary goal is to provide a structured framework that enables PHP users at
all levels to rapidly develop robust web applications, without any loss to
flexibility.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"tickets cakephp" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/tickets-cakephp?hl=en
-~----------~----~----~----~------~----~------~--~---