Please, think twice before creating (and posting) your homemade solution for ordering an array by a field.
PHP already has a solution for this; usort, which is about x40 faster than any other solution.
If creating a callback for each case hurts, you can do something like this:
<?php
/**
* @author Lucas Dománico
*/
class util {
static private $sortfield = null;
static private $sortorder = 1;
static private function sort_callback(&$a, &$b) {
if($a[self::$sortfield] == $b[self::$sortfield]) return 0;
return ($a[self::$sortfield] < $b[self::$sortfield])? -self::$sortorder : self::$sortorder;
}
static function sort(&$v, $field, $asc=true) {
self::$sortfield = $field;
self::$sortorder = $asc? 1 : -1;
usort($v, array('util', 'sort_callback'));
}
}
# Usage:
for($i=0; $i<1000 ;$i++) {
$v[] = array('score'=>rand(1,10000));
}
util::sort($v, 'score');
?>
sort
(PHP 4, PHP 5)
sort — Sort an array
Descrierea
This function sorts an array. Elements will be arranged from lowest to highest when this function has completed.
Parametri
- array
-
The input array.
- sort_flags
-
The optional second parameter sort_flags may be used to modify the sorting behavior using these values:
Sorting type flags:
- SORT_REGULAR - compare items normally (don't change types)
- SORT_NUMERIC - compare items numerically
- SORT_STRING - compare items as strings
- SORT_LOCALE_STRING - compare items as strings, based on the current locale. Added in PHP 4.4.0 and 5.0.2. Before PHP 6, it uses the system locale, which can be changed using setlocale(). Since PHP 6, you must use the i18n_loc_set_default() function.
Valorile întroarse
Întoarce valoarea TRUE în cazul succesului sau FALSE în cazul eşecului.
Istoria schimbărilor
| Versiunea | Descriere |
|---|---|
| 4.0.0 | The sort_flags parameter was added. |
Exemple
Example #1 sort() example
<?php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
?>
Exemplul de mai sus va afişa:
fruits[0] = apple fruits[1] = banana fruits[2] = lemon fruits[3] = orange
The fruits have been sorted in alphabetical order.
Note
Notă: Această funcţie atribuie chei noi elementelor din array . Ea va elimina cheile existente, care posibil au fost atribuite, în loc doar să rearanjeze cheile.
Notă: Like most PHP sorting functions, sort() uses an implementation of » Quicksort.
Be careful when sorting arrays with mixed types values because sort() can produce unpredictable results.
Vedeţi de asemenea
sort
26-Sep-2008 01:04
09-Sep-2008 07:43
To sort an array of multiple text fields alphabetically you have to make the text lowercase before sorting the array. Otherwise PHP puts acronyms before words. You can see this in my example code. Simply store the original text field at the end of the array line and call it later from there. You can safely ignore the lowercase version which is added to the start of the array line.
<?php
echo '<pre>ORIGINAL DATA:
<br />';
$data = array(
'Saturn|7|8|9|0||',
'Hello|0|1|2|3||',
'SFX|5|3|2|4||',
'HP|9|0|5|6||'
);
print_r($data);
sort($data);
reset($data);
echo '<br />RAW SORT:
<br />';
print_r($data);
for ($c = 0; $c < count($data); $c++) {
list ($letter,$g1,$g2,$g3,$g4,$end) = explode ('|', $data[$c]);
$lowercase = strtolower($letter);
$data2[$c] = array($lowercase,$g1,$g2,$g3,$g4,$letter);
}
sort($data2);
reset($data2);
echo '<br />LOWERCASE SORT:
<br />';
print_r($data2);
echo '</pre>';
?>
23-Jan-2008 03:46
This function will sort entity letters eg:é
I hope that help someone
function sort_entity($array) {
$total = count($array);
for ($i=0;$i<$total;$i++) {
if ($array[$i]{0} == '&') {
$array[$i] = $array[$i]{1}.$array[$i];
} else {
$array[$i] = $array[$i]{0}.$array[$i];
}
}
sort($array);
for ($i=0;$i<$total;$i++) {
$array[$i] = substr($array[$i],1);
}
return $array;
}
07-Jan-2008 12:25
Update to the msort code posted by: alishahnovin
I had a problem with the msort function not being case sensitive. All capital letters A-Z would list in order then all lowercase letters would follow.
the line:
if ($item[$id]<$array[$lowest_id][$id]) {
was changed to:
if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
<?php
function msort($array, $id="id", $sort_ascending=true) {
$temp_array = array();
while(count($array)>0) {
$lowest_id = 0;
$index=0;
foreach ($array as $item) {
if (isset($item[$id])) {
if ($array[$lowest_id][$id]) {
if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
$lowest_id = $index;
}
}
}
$index++;
}
$temp_array[] = $array[$lowest_id];
$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
}
if ($sort_ascending) {
return $temp_array;
} else {
return array_reverse($temp_array);
}
}
?>
02-Sep-2007 06:02
Here's a variation on the above function to sort arrays with more than one key by an arbitrary key's value.
This function allows sorting of an array of objects too
<?php
/**
* Sorts an array of objects by the value of one of the object properties or array keys
*
* @param array $array
* @param key value $id
* @param boolean $sort_ascending
* @param boolean $is_object_array
* @return array
*/
function vsort($array, $id="id", $sort_ascending=true, $is_object_array = false) {
$temp_array = array();
while(count($array)>0) {
$lowest_id = 0;
$index=0;
if($is_object_array){
foreach ($array as $item) {
if (isset($item->$id)) {
if ($array[$lowest_id]->$id) {
if ($item->$id<$array[$lowest_id]->$id) {
$lowest_id = $index;
}
}
}
$index++;
}
}else{
foreach ($array as $item) {
if (isset($item[$id])) {
if ($array[$lowest_id][$id]) {
if ($item[$id]<$array[$lowest_id][$id]) {
$lowest_id = $index;
}
}
}
$index++;
}
}
$temp_array[] = $array[$lowest_id];
$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
}
if ($sort_ascending) {
return $temp_array;
} else {
return array_reverse($temp_array);
}
}
?>
Sample Usage:
<?php
$nodes = vsort($nodes,'term_data_weight', false, true);
print '<pre>'.print_r($nodes,1).'</pre>';
?>
22-Jul-2007 05:42
Hi, this is my version of sorting an array by field.
From browsing previous versions it pretty much resembles bluej's version. It's way much faster than the versions where the sorting is made "manually" rather than with native php functions, and I wrote it after trying one of those that kept timing out my scripts if I had 10000 posts.
This one preserves numerical keys as well. So if you want to re-index the array after using it with numerical keys just use the array_values on the result. However there are cases where the key actually means something even if it's a number (id etc) so I didn't want to take it for granted that it should be reindexed.
Cheers
Q
<?php
function sortArrayByField
(
$original,
$field,
$descending = false
)
{
$sortArr = array();
foreach ( $original as $key => $value )
{
$sortArr[ $key ] = $value[ $field ];
}
if ( $descending )
{
arsort( $sortArr );
}
else
{
asort( $sortArr );
}
$resultArr = array();
foreach ( $sortArr as $key => $value )
{
$resultArr[ $key ] = $original[ $key ];
}
return $resultArr;
}
?>
19-Jul-2007 04:16
Someone asked me if the msort I posted below can do a sort by descending... (as it sorts by ascending...smallest to greatest).
It's a simple fix with an extra param, and then an array_reverse...but for the lazy, here you are:
<?php
function msort($array, $id="id", $sort_ascending=true) {
$temp_array = array();
while(count($array)>0) {
$lowest_id = 0;
$index=0;
foreach ($array as $item) {
if (isset($item[$id])) {
if ($array[$lowest_id][$id]) {
if ($item[$id]<$array[$lowest_id][$id]) {
$lowest_id = $index;
}
}
}
$index++;
}
$temp_array[] = $array[$lowest_id];
$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
}
if ($sort_ascending) {
return $temp_array;
} else {
return array_reverse($temp_array);
}
}
?>
<?php
//oh no, this is not in the ordered by id!!
$data[] = array("item"=>"item 1", "id"=>1);
$data[] = array("item"=>"item 3", "id"=>3);
$data[] = array("item"=>"item 2", "id"=>2);
var_dump( msort($data, "id", false) ); //just msort it...greatest to smallest
var_dump( msort($data, "id") ); //just msort it...smallest to greatest
/* outputs
array
0 =>
array
'item' => 'item 3' (length=6)
'id' => 3
1 =>
array
'item' => 'item 2' (length=6)
'id' => 2
2 =>
array
'item' => 'item 1' (length=6)
'id' => 1
array
0 =>
array
'item' => 'item 1' (length=6)
'id' => 1
1 =>
array
'item' => 'item 2' (length=6)
'id' => 2
2 =>
array
'item' => 'item 3' (length=6)
'id' => 3
*/
?>
10-Jul-2007 03:03
The sort2d I posted before did nothing by default--that'll teach me to copy-and-paste without thinking. Its sort function has to be associative. I've changed the default to asort. natcasesort does actually work, though.
// $sort used as variable function--can be natcasesort, for example
// WARNING: $sort must be associative
function sort2d( &$arrIn, $index = null, $sort = 'asort') {
// pseudo-secure--never allow user input into $sort
if (strpos($sort, 'sort') === false) {$sort = 'asort';}
$arrTemp = Array();
$arrOut = Array();
foreach ( $arrIn as $key=>$value ) {
$arrTemp[$key] = is_null($index) ? reset($value) : $value[$index];
}
$sort($arrTemp);
foreach ( $arrTemp as $key=>$value ) {
$arrOut[$key] = $arrIn[$key];
}
$arrIn = $arrOut;
}
Also, uasort is probably actually the better solution for most 2d sorting, unless you're sorting by a dozen different indexes.
04-Jul-2007 01:14
This is my way of sorting files into date modified date order. It worked for me!
$dir='topics';
$ext='php5';
$files=scandir($dir);
foreach($files as $fs){
if(($fs!='.')&&($fs!='..')){
$fs1.='¬'.filemtime($dir.'/'.$fs).'#'.$fs;
}
}
$fs2=split('[¬]',$fs1);
arsort($fs2);
foreach($fs2 as $fs3){
if(eregi($ext,$fs3)){
$fs4.='¬'.$fs3;
}
}
$fs5=split('[#]',$fs4);
foreach($fs5 as $fs6){
if(eregi($ext,$fs6)){
$fs7.='¬'.$fs6;
}
}
$fs8=split('[¬]',$fs7);
foreach($fs8 as $fs9){
$file_list.=$fs9.'
</br>';
}
print $file_list;
23-Jun-2007 08:29
here is little script which will merge arrays, remove duplicates and sort it by alphabetical order:
<?php
$array1 = array('apple', 'banana','pear');
$array2 = array('grape', 'pear','orange');
function array_unique_merge_sort($array1, $array2){
$array = array_unique(array_merge($array1, $array2));
sort($array);
foreach ($array as $key => $value) {
$new[$key] = $value;
}
return $new;
}
print_r (array_unique_merge_sort($array1, $array2));
?>
this will print out:
Array ( [0] => apple [1] => banana [2] => grape [3] => orange [4] => pear )
07-Jun-2007 03:05
One more solution for multidimensional sort: variable functions.
<?php
// $sort used as variable function--can be natcasesort, for example
function sort2d( &$arrIn, $index = null, $sort = 'sort') {
// pseudo-secure--never allow user input into $sort
if (strpos($sort, 'sort') === false) {$sort = 'sort';}
$arrTemp = Array();
$arrOut = Array();
foreach ( $arrIn as $key=>$value ) {
reset($value);
$arrTemp[$key] = is_null($index) ? current($value) : $value[$index];
}
$sort($arrTemp);
foreach ( $arrTemp as $key=>$value ) {
$arrOut[$key] = $arrIn[$key];
}
$arrIn = $arrOut;
}
?>
It appears to me that there are only two algorithms being proposed here (several times each):
1) copy into temp, pass temp to sort function, re-order by temp
2) implement search function in PHP
I'm curious whether anyone's implementation of (2) can beat (1) for speed. Someone have a fast PHP mergesort they can benchmark against this one? Obviously, the fact that the (1) solutions use at least two, possibly three times the memory is a drawback, but I expect that for most of us, speed is significantly more important than memory. Maybe I'll check it myself when I have a minute.
28-May-2007 10:29
Here's my fixed up msort array. What it does is goes through a multidimensional array, and sorts it by the desired key (defaulting to 'id').
So, for example, if you have an array like:
array[0]['value'] = "statement 2"
array[0]['id'] = "2"
array[1]['value'] = "statement 3"
array[1]['id'] = "3"
array[2]['value'] = "statement 1"
array[2]['id'] = "1"
it would rearrange and return the array to be like:
array[0]['value'] = "statement 1"
array[0]['id'] = "1"
array[1]['value'] = "statement 2"
array[1]['id'] = "2"
array[2]['value'] = "statement 3"
array[2]['id'] = "3"
The 'id' index can start at any point, and any array item missing the id index will be added to the end.
<?php
function msort($array, $id="id") {
$temp_array = array();
while(count($array)>0) {
$lowest_id = 0;
$index=0;
foreach ($array as $item) {
if (isset($item[$id]) && $array[$lowest_id][$id]) {
if ($item[$id]<$array[$lowest_id][$id]) {
$lowest_id = $index;
}
}
$index++;
}
$temp_array[] = $array[$lowest_id];
$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
}
return $temp_array;
}
?>
Ex:
<?php
//oh no, this is not in the ordered by id!!
$data[] = array("item"=>"item 4");
$data[] = array("item"=>"item 1", "id"=>1);
$data[] = array("item"=>"item 3", "id"=>3);
$data[] = array("item"=>"item 2", "id"=>2);
var_dump( msort($data) ); //just msort it!
/* outputs
array
0 =>
array
'item' => 'item 1' (length=6)
'id' => 1
1 =>
array
'item' => 'item 2' (length=6)
'id' => 2
2 =>
array
'item' => 'item 3' (length=6)
'id' => 3
3 =>
array
'item' => 'item 4' (length=6)
*/
?>
25-May-2007 04:11
I had a multidimensional array, which needed to be sorted by one of the keys. This is what I came up with...
<?php
function msort($array, $id="id") {
$temp_array = array();
while(count($array)>0) {
$lowest_id = 0;
$index=0;
foreach ($array as $item) {
if ($item[$id]<$array[$lowest_id][$id]) {
$lowest_id = $index;
}
$index++;
}
$temp_array[] = $array[$lowest_id];
$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
}
return $temp_array;
}
?>
Ex:
<?php
//oh no, this is not in the ordered by id!!
$data[] = array("item"=>"item 4", "id"=>4);
$data[] = array("item"=>"item 1", "id"=>1);
$data[] = array("item"=>"item 3", "id"=>3);
$data[] = array("item"=>"item 2", "id"=>2);
var_dump( msort($data) ); //just msort it!
/* outputs
array
0 =>
array
'item' => 'item 1' (length=6)
'id' => 1
1 =>
array
'item' => 'item 2' (length=6)
'id' => 2
2 =>
array
'item' => 'item 3' (length=6)
'id' => 3
3 =>
array
'item' => 'item 4' (length=6)
'id' => 4
*/
?>
14-May-2007 03:38
How to use an anonymous array to sort any associative array by an arbitrary key (or nested key):
$order = -1; # -1 = Ascending. Use 1 for descending.
$sortby = "['key1']['subkey']";
$mysort = create_function('$a,$b', "\$a1=\$a$sortby;\$b1=\$b$sortby; if (\$a1==\$b1) return 0; else return (\$a1<\$b1) ? $order : 0- $
order;");
uasort($assocarray, $mysort);
You can use this in a recursive function if necessary (which is why I developed it).
09-May-2007 07:27
The bubble sort below will sort an array of objects based on any one of the values contained in them.
usage: objectSort($details, 'percent');
function objectSort(&$data, $key)
{
for ($i = count($data) - 1; $i >= 0; $i--)
{
$swapped = false;
for ($j = 0; $j < $i; $j++)
{
if ($data[$j]->$key > $data[$j + 1]->$key)
{
$tmp = $data[$j];
$data[$j] = $data[$j + 1];
$data[$j + 1] = $tmp;
$swapped = true;
}
}
if (!$swapped) return;
}
}
15-Mar-2007 07:52
An improvement on the very nice code submitted by alex [at] vkpb [dot] com. This will preserve the keys if the array is numeric:
function SortDataSet($aArray, $sField, $bDescending = false)
{
$bIsNumeric = IsNumeric($aArray);
$aKeys = array_keys($aArray);
$nSize = sizeof($aArray);
for ($nIndex = 0; $nIndex < $nSize - 1; $nIndex++)
{
$nMinIndex = $nIndex;
$objMinValue = $aArray[$aKeys[$nIndex]][$sField];
$sKey = $aKeys[$nIndex];
for ($nSortIndex = $nIndex + 1; $nSortIndex < $nSize; ++$nSortIndex)
{
if ($aArray[$aKeys[$nSortIndex]][$sField] < $objMinValue)
{
$nMinIndex = $nSortIndex;
$sKey = $aKeys[$nSortIndex];
$objMinValue = $aArray[$aKeys[$nSortIndex]][$sField];
}
}
$aKeys[$nMinIndex] = $aKeys[$nIndex];
$aKeys[$nIndex] = $sKey;
}
$aReturn = array();
for($nSortIndex = 0; $nSortIndex < $nSize; ++$nSortIndex)
{
$nIndex = $bDescending ? $nSize - $nSortIndex - 1: $nSortIndex;
$aReturn[$aKeys[$nIndex]] = $aArray[$aKeys[$nIndex]];
}
return $bIsNumeric ? array_values($aReturn) : $aReturn;
}
function IsNumeric($aArray)
{
$aKeys = array_keys($aArray);
for ($nIndex = 0; $nIndex < sizeof($aKeys); $nIndex++)
{
if (!is_int($aKeys[$nIndex]) || ($aKeys[$nIndex] != $nIndex))
{
return false;
}
}
return true;
}
01-Feb-2007 05:40
Commenting on note http://www.php.net/manual/en/function.sort.php#62311 :
Sorting an array of objects will not always yield the results you desire.
As pointed out correctly in the note above, sort() sorts the array by value of the first member variable. However, you can not always assume the order of your member variables! You must take into account your class hierarchy!
By default, PHP places the inherited member variables on top, meaning your first member variable is NOT the first variable in your class definition!
However, if you use code analyzers or a compile cache, things can be very different. E.g., in eAccelerator, the inherited member variables are at the end, meaning you get different sort results with caching on or off.
Conclusion:
Never use sort on arrays with values of a type other than scalar or array.
26-Jan-2007 03:36
Sorting of an array by a method of inserts.
<?
function sortByField($multArray,$sortField,$desc=true){
$tmpKey='';
$ResArray=array();
$maIndex=array_keys($multArray);
$maSize=count($multArray)-1;
for($i=0; $i < $maSize ; $i++) {
$minElement=$i;
$tempMin=$multArray[$maIndex[$i]][$sortField];
$tmpKey=$maIndex[$i];
for($j=$i+1; $j <= $maSize; $j++)
if($multArray[$maIndex[$j]][$sortField] < $tempMin ) {
$minElement=$j;
$tmpKey=$maIndex[$j];
$tempMin=$multArray[$maIndex[$j]][$sortField];
}
$maIndex[$minElement]=$maIndex[$i];
$maIndex[$i]=$tmpKey;
}
if($desc)
for($j=0;$j<=$maSize;$j++)
$ResArray[$maIndex[$j]]=$multArray[$maIndex[$j]];
else
for($j=$maSize;$j>=0;$j--)
$ResArray[$maIndex[$j]]=$multArray[$maIndex[$j]];
return $ResArray;
}
// make array
$array['aaa']=array("name"=>"vasia","order"=>1);
$array['bbb']=array("name"=>"petia","order"=>2);
$array['ccc']=array("name"=>"kolia","order"=>3);
$array['ddd']=array("name"=>"zenia","order"=>4);
// set sort
$SortOrder=0; // desc by default , 1- asc
var_dump(sortByField($array,'order',$SortOrder));
array
'ddd' =>
array
'name' => 'zenia' (length=5)
'order' => 4
'aaa' =>
array
'name' => 'vasia' (length=5)
'order' => 1
'bbb' =>
array
'name' => 'petia' (length=5)
'order' => 2
'ccc' =>
array
'name' => 'kolia' (length=5)
'order' => 3
?>
28-Nov-2006 05:54
Simple way, how to sort an array without loosing keys:
<?php
$sizes = $bad = $good = array("d" => "dddd", "a" => "aaaa", "c" => "cccc", "e" => "eeee", "b" => "bbbb");
// original
print_r($sizes);
/*
Array
(
[d] => dddd
[a] => aaaa
[c] => cccc
[e] => eeee
[b] => bbbb
)
*/
// bad way
sort($bad);
print_r($bad);
/*
Array
(
[0] => aaaa
[1] => bbbb
[2] => cccc
[3] => dddd
[4] => eeee
)
*/
// good way
$good=array_flip($good);
ksort($good);
$good=array_flip($good);
print_r($good);
/*
Array
(
[a] => aaaa
[b] => bbbb
[c] => cccc
[d] => dddd
[e] => eeee
)
*/
?>
15-Nov-2006 07:24
/**
* Will sort an array by the value of the applied lambda function to each element
* without loosing the keys!
* @param unknown_type $arr
* @param unknown_type $func of the form mixvar func(your object)
*/
function sortByFunc(&$arr, $func) {
$tmpArr = array();
foreach ($arr as $k => &$e) {
$tmpArr[] = array('f' => $func($e), 'k' => $k, 'e' =>&$e);
}
sort($tmpArr);
$arr = array();
foreach($tmpArr as &$fke) {
$arr[$fke['k']] = &$fke['e'];
}
}
example:
$arr = array(
1 => array('name' => 'eran', 'age' => 30),
2 => array('name' => 'naama', 'age' => 29),
3 => array('name' => 'a', 'age' => 11),
4 => array('name' => 'b', 'age' => 51),
5 => array('name' => 'z', 'age' => 5),
);
foreach($arr as $key => $val) {
echo "<br> $key => (" . $val['name'] . " ," . $val['age'] . ")";
}
sortByFunc($arr,create_function('$element','return $element["age"];'));
echo "<br> now sorted:";
foreach($arr as $key => $val) {
echo "<br> $key => (" . $val['name'] . " ," . $val['age'] . ")";
}
output:
1 => (eran ,30)
2 => (naama ,29)
3 => (a ,11)
4 => (b ,51)
5 => (z ,5)
now sorted:
5 => (z ,5)
3 => (a ,11)
2 => (naama ,29)
1 => (eran ,30)
4 => (b ,51)
21-Jul-2006 10:31
Here is how you would open a file, and put each line into an array. This sorts by the first field $title field. The next thing I would like to figure out is how to do this same sort but with the ability to skip the first word of the title. Like if the title has an "a" or "the" it would skip that portion of the sort.
$currentfile = "file.txt";
$fp = fopen( $currentfile, "r" ) or die("Couldn't open $currentfile");
while ( ! feof( $fp ) ) {
$line[] = fgets( $fp, 1024 );
foreach ( $line as $newarray ) {
}
$newline[] = trim($newarray);
sort($newline);
list($title1, $titleurl1, $rating1) = split ('\|',
$newline[0]);
list($title2, $titleurl2, $rating2) = split ('\|',
$newline[1]);
list($title3, $titleurl3, $rating3) = split ('\|',
$newline[2]);
list($title4, $titleurl4, $rating4) = split ('\|',
$newline[3]);
14-Jul-2006 04:28
<?php
/**
This sort function allows you to sort an associative array while "sticking" some fields.
$sticky_fields = an array of fields that should not be re-sorted. This is a method of achieving sub-sorts within contiguous groups of records that have common data in some fields.
For example:
$a = array();
$a []= array(
'name' => 'Sam',
'age' => 23,
'hire_date' => '2004-01-01'
);
$a []= array(
'name' => 'Sam',
'age' => 44,
'hire_date' => '2003-03-23'
);
$a []= array(
'name' => 'Jenny',
'age' => 20,
'hire_date' => '2000-12-31'
);
$a []= array(
'name' => 'Samantha',
'age' => 50,
'hire_date' => '2000-12-14'
);
$sticky_fields = array( 'name' );
print_r( stickysort( $a, 'age', DESC_NUM, $sticky_fields ) );
OUTPUT:
Array
(
[0] => Array
(
[name] => Sam
[age] => 44
[hire_date] => 2003-03-23
)
[1] => Array
(
[name] => Sam
[age] => 23
[hire_date] => 2004-01-01
)
[2] => Array
(
[name] => Jenny
[age] => 20
[hire_date] => 2000-12-31
)
[3] => Array
(
[name] => Samantha
[age] => 50
[hire_date] => 2000-12-14
)
)
Here's why this is the correct output - the "name" field is sticky, so it cannot change its sort order. Thus, the "age" field is only sorted as a sub-sort within records where "name" is identical. Thus, the "Sam" records are reversed, because 44 > 23, but Samantha remains at the bottom, even though her age is 50. This is a way of achieving "sub-sorts" and "sub-sub-sorts" (and so on) within records of identical data for specific fields.
Courtesy of the $5 Script Archive: http://www.tufat.com
**/
define( 'ASC_AZ', 1000 );
define( 'DESC_AZ', 1001 );
define( 'ASC_NUM', 1002 );
define( 'DESC_NUM', 1003 );
function stickysort( $arr, $field, $sort_type, $sticky_fields = array() ) {
$i = 0;
foreach ($arr as $value) {
$is_contiguous = true;
if(!empty($grouped_arr)) {
$last_value = end($grouped_arr[$i]);
if(!($sticky_fields == array())) {
foreach ($sticky_fields as $sticky_field) {
if ($value[$sticky_field] <> $last_value[$sticky_field]) {
$is_contiguous = false;
break;
}
}
}
}
if ($is_contiguous)
$grouped_arr[$i][] = $value;
else
$grouped_arr[++$i][] = $value;
}
$code = '';
switch($sort_type) {
case ASC_AZ:
$code .= 'return strcasecmp($a["'.$field.'"], $b["'.$field.'"]);';
break;
case DESC_AZ:
$code .= 'return (-1*strcasecmp($a["'.$field.'"], $b["'.$field.'"]));';
break;
case ASC_NUM:
$code .= 'return ($a["'.$field.'"] - $b["'.$field.'"]);';
break;
case DESC_NUM:
$code .= 'return ($b["'.$field.'"] - $a["'.$field.'"]);';
break;
}
$compare = create_function('$a, $b', $code);
foreach($grouped_arr as $grouped_arr_key=>$grouped_arr_value)
usort ( $grouped_arr[$grouped_arr_key], $compare );
$arr = array();
foreach($grouped_arr as $grouped_arr_key=>$grouped_arr_value)
foreach($grouped_arr[$grouped_arr_key] as $grouped_arr_arr_key=>$grouped_arr_arr_value)
$arr[] = $grouped_arr[$grouped_arr_key][$grouped_arr_arr_key];
return $arr;
}
?>
10-Jul-2006 08:58
<?php
/**
This sort function allows you to sort an associative array while "sticking" some fields.
$sticky_fields = an array of fields that should not be re-sorted. This is a method of achieving sub-sorts within contiguous groups of records that have common data in some fields.
Courtesy of the $5 Script Archive: http://www.tufat.com
**/
define( 'ASC_AZ', 1000 );
define( 'DESC_AZ', 1001 );
define( 'ASC_NUM', 1002 );
define( 'DESC_NUM', 1003 );
function stickysort( $arr, $field, $sort_type, $sticky_fields = array() ) {
$i = 0;
foreach ($arr as $value) {
$is_contiguous = true;
if(!empty($grouped_arr)) {
$last_value = end($grouped_arr[$i]);
if(!($sticky_fields == array())) {
foreach ($sticky_fields as $sticky_field) {
if ($value[$sticky_field] <> $last_value[$sticky_field]) {
$is_contiguous = false;
break;
}
}
}
}
if ($is_contiguous)
$grouped_arr[$i][] = $value;
else
$grouped_arr[++$i][] = $value;
}
$code = '';
switch($sort_type) {
case ASC_AZ:
$code .= 'return strcasecmp($a["'.$field.'"], $b["'.$field.'"]);';
break;
case DESC_AZ:
$code .= 'return (-1*strcasecmp($a["'.$field.'"], $b["'.$field.'"]));';
break;
case ASC_NUM:
$code .= 'return ($a["'.$field.'"] - $b["'.$field.'"]);';
break;
case DESC_NUM:
$code .= 'return ($b["'.$field.'"] - $a["'.$field.'"]);';
break;
}
$compare = create_function('$a, $b', $code);
foreach($grouped_arr as $grouped_arr_key=>$grouped_arr_value)
usort ( $grouped_arr[$grouped_arr_key], $compare );
$arr = array();
foreach($grouped_arr as $grouped_arr_key=>$grouped_arr_value)
foreach($grouped_arr[$grouped_arr_key] as $grouped_arr_arr_key=>$grouped_arr_arr_value)
$arr[] = $grouped_arr[$grouped_arr_key][$grouped_arr_arr_key];
return $arr;
}
?>
10-Jul-2006 08:57
<?php
/**
This sort function allows you to sort an associative array while "sticking" some fields.
$sticky_fields = an array of fields that should not be re-sorted. This is a method of achieving sub-sorts within contiguous groups of records that have common data in some fields.
Courtesy of the $5 Script Archive: http://www.tufat.com
**/
define( 'ASC_AZ', 1000 );
define( 'DESC_AZ', 1001 );
define( 'ASC_NUM', 1002 );
define( 'DESC_NUM', 1003 );
function stickysort( $arr, $field, $sort_type, $sticky_fields = array() ) {
$i = 0;
foreach ($arr as $value) {
$is_contiguous = true;
if(!empty($grouped_arr)) {
$last_value = end($grouped_arr[$i]);
if(!($sticky_fields == array())) {
foreach ($sticky_fields as $sticky_field) {
if ($value[$sticky_field] <> $last_value[$sticky_field]) {
$is_contiguous = false;
break;
}
}
}
}
if ($is_contiguous)
$grouped_arr[$i][] = $value;
else
$grouped_arr[++$i][] = $value;
}
$code = '';
switch($sort_type) {
case ASC_AZ:
$code .= 'return strcasecmp($a["'.$field.'"], $b["'.$field.'"]);';
break;
case DESC_AZ:
$code .= 'return (-1*strcasecmp($a["'.$field.'"], $b["'.$field.'"]));';
break;
case ASC_NUM:
$code .= 'return ($a["'.$field.'"] - $b["'.$field.'"]);';
break;
case DESC_NUM:
$code .= 'return ($b["'.$field.'"] - $a["'.$field.'"]);';
break;
}
$compare = create_function('$a, $b', $code);
foreach($grouped_arr as $grouped_arr_key=>$grouped_arr_value)
usort ( $grouped_arr[$grouped_arr_key], $compare );
$arr =