|
sort
Sort an array
(PHP 4, PHP 5)
Example 323. sort() example<?php The above example will output: fruits[0] = apple Related Examples ( Source code ) » sort Examples ( Source code ) » Elements of the enumerated array are numbers Examples ( Source code ) » array_multisort Examples ( Source code ) » arsort Sort an array in reverse order and maintain index association Examples ( Source code ) » Sort associate array Examples ( Source code ) » sort an associative array on the basis of keys Examples ( Source code ) » asort () function retains the array's keys in the original state Examples ( Source code ) » To reverse sort an enumerated array, use the rsort () function Examples ( Source code ) » Using the sort () Function Examples ( Source code ) » Using usort() to Sort a Multidimensional Array by One of Its Fields Examples ( Source code ) » Using uasort() to Sort a Multdimensional Associative Array by One of Its Fields Examples ( Source code ) » Using uksort() to Sort an Associative Array by the Length of Its Keys Examples ( Source code ) » Sort associate array Examples ( Source code ) » Create function from string Examples ( Source code ) » Create a swf slideshow Examples ( Source code ) » E-mail address validation class Code Examples / Notes » sortjerome a-t+ yamafoto d*o*t com
when sorting an array, beware of variable type from elements you put in this array Example: $a = 2; // $a is an integer $b = 'item'; $arr = array($a, $b); sort($arr); print_r($arr); this will output: $arr[0] = 'item'; $arr[1] = 2; $a = '2'; // $a is a string $b = 'item'; $arr = array($a, $b); sort($arr); print_r($arr); this will output: $arr[0] = '2'; $arr[1] = 'item' to avoid this problem use: sort($arr, SORT_STRING) ultrafunkula
What you really want is asort(). The neat thing about PHP arrays is that even though they have a traditional numerical index, they are not defined by it. What I mean by this is if you define an array $data[], then $data[2] does not necessarily exist between $data[1] and $data[3]. So if you asort() by the artist name and then use each() to recover the array elements in the order they exist(rather than an incremental loop which ties you to their arbitrary numerical key), you can sort your data by any dimension of your array. Try this out: $data[0][1]='Title 2'; $data[0][2]='Title 1'; $data[0][0]='Title 3'; $data[1][1]='Barney'; $data[1][0]='Charlie'; $data[1][2]='Al'; $data[2][2]='Sing the song of Al'; $data[2][1]='Jam with Barney'; $data[2][0]='Charlie Rocks'; while (list($key) = each($data[1])) { print $data[0][$key].",".$data[1][$key].",".$data[2][$key]." "; } asort($data[1]); while (list($key) = each($data[1])) { print $data[0][$key].",".$data[1][$key].",".$data[2][$key]." "; } The interesting part is that the first, UNSORTED array doesn't come out in numerical order, because it wasn't put in that way. If you asort($data[2]) you'll sort by lyrics, and so on. Just make sure you remember to each() by the same dimension as you asort(). nbs studio
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; whatever
The usort solution below still has problems when sorting strings of different lengths, just like the other flavors of sort that I've tried. Here's a solution that I came up with -- it's kinda ugly, and it might not be practical for large arrays, but it's works great for me. I'm getting some people's names out of mySQL and placing them in an array like this: "$lastname, $firstname $middlename". Because some people don't have middle names, "sort" screws up the alphabetization. So what I've done is this: $index = 0; while ($rows = mysql_fetch_array($sqlResult)) { extract($rows); $my_array[$index]['sortname'] = strtolower(preg_replace("/[^a-zA-Z]/", "", "$lastname$firstname$middlename")); $my_array[$index]['name'] = trim("$lastname, $firstname $middlename"); $index++; } sort($my_array); // now in perfect alpha order My "hack" is in the fourth line -- I take the entire name, last name first, and use preg_replace() to take out all non-letter characters, and then used strtolower() to make it all lowercase to ensure all letters would be treated equally by PHP. This goes into the ['sortname'] key within the array. (The ['sortname'] value has to come before ['name'], or else the array will be sorted by ['name'] instead.) This gives me: Array ( [0] => Array ( [sortname] => shmojoe [name] => Shmo, Joe ) [1] => Array ( [sortname] => shmojoem [name] => Shmo, Joe M ) ) ... and so on So the array gets sorted by ['sortname'], which never needs to be displayed, and the associated ['name'] can be displayed in perfect alphabetical order, whether there is one name, two names or three. And because ['sortname'] is letters only, it works great for hyphenated last names or ones with apostrophes, like Smith-Jones or O'Donnell. I feel that the dual preg_replace() and strtolower() may not be the best theoretical solution, and I don't know how it would run on a really large array, but as I said, it's a great solution for my little site. richard dot c dot mitchell
The usort function can be used to sort multi-dimension arrays, also. To do a case-insensitive sort on the 7th column of a two-dimensional array: usort($listing, create_function('$a,$b','return strcasecmp($a[7],$b[7]);')); When using associative arrays: usort($listing, create_function('$a,$b','return strcasecmp($a["name"],$b["name"]);')); Case-sensitive, descending (just change '$a,$b' to '$b,$a'): usort($listing, create_function('$b,$a','return strcmp($a["name"],$b["name"]);')); A two-dimensional array of numbers (7th column, ascending): usort($listing, create_function('$a,$b','return $a[7]==$b[7]?0:($a[7]<$b[7]?-1:1);')); bluej100@gmail
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. matthew hood
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; } } alex
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 ?> alishahnovin
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 */ ?> crudo
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 ) */ ?> john dot dutcher
Regarding the array sorting of names by 'whatever' .... That post addresses a nearly identical issue with sorting that I also have. I just wanted to inquire though.........wouldn't the building of the 'sortname' value require that the last name and first name be padded to their full size as they are placed into the 'sortname' field in order to get proper sorting/alignment ? Otherwise would one have ....... dutcherjohnf (Dutcher, John F) dutchrogera (Dutch, Roger A) dutmauriceh (Dut, Maurice H) Instead of: dut maurice h dutch roger a dutcher john f John D. ab454
Other Way than below: just use asort() ;)
bluej100@gmail
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. misillet
Note that using sort() it seems to sort by ASCII code, because "AC" is before "Ab" in the result array
runmaster
Note that sort() is void, so an assignment like $foo_array = sort( $foo_array ); wont work. In result you cannot combine sort() for use with other array-related functions just like array_unique() or array_values(). None of the following statements works: sort( array_unique( $foo_array ) ); // returns empty string $foo_array = array_unique( sort( $foo_array) ); // returns parameter failure The only way to combine those functions is to apply sort() in a single line statement. So please dont waste your time with hours of debugging like me before I found out, its void... ;-) matias
Lets say you have the following array: $array1 = Array(third => "Some text 3", second => "Some text 2", first => "Some text 1", fourth => "Some text 4" ); and you want to sort it by first,second,third, fourth. Very easy! Just create a second array: $array2 = Array(first => "", second => "", third => "", fourth => ""); and do: $result = array_merge($array2,$array1); now $result = Array(first => "Some text 1",second => "Some text 2",third => "Some text 3",fourth => "Some text 4"); This is very usefull when you want to print data out of a database table for example, but you would like to give it a custom order. teunkloosterman
Just to show how it sorts: <?php $array = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", "!", "@", "#", "\\\$", "%", "^", "&", "*", "(", ")", "_", "-", "=", "+", "\\\\", "|", ",", "<", ".", ">", "?", "'", "\\\"", "`", "~"); sort($array); echo implode("", $array); ?> returns: !"#$%&'()*+,-.0123456789<=>? @ABCDEFGHIJKLMNOPQRSTUVWXYZ \^_`abcdefghijklmnopqrstuvwxyz|~ note: the result begins with a space james
It's useful to know that if you're using this function on a multidimensional array, php will sort the first key, then the second and so on. This is similar to being able to use SQL to order by field1, field2 etc. So: Array ( [0] => Array ( [category] => work [name] => Smith ) [1] => Array ( [category] => play [name] => Johnson ) [2] => Array ( [category] => work [name] => Berger ) ) will become: Array ( [0] => Array ( [category] => play [name] => Johnson ) [1] => Array ( [category] => work [name] => Berger ) [2] => Array ( [category] => work [name] => Smith ) ) Hope it helps someone. anthony
In a brief addition to the previous poster's message, the ascending sorting order used by PHP directly corresponds to ISO-8859-1 (ASCII). Therefore the character \48 (numeral 0) would be placed before the character \82 (R), which would be placed before the character \110 (n), and so forth.
arjan321
Ik you want to sort case insensitive, use the natcasesort()
14-mar-2002 10:09
If you want to sort an array according to your locale do the following: (de_DE as example) setlocale("LC_ALL","de_DE"); usort($arraytobesorted, 'strcoll'); --ed: In PHP 4.4 and PHP 5.0 you can do: setlocale("LC_ALL", "de_DE"); sort($arraytobesorted, SORT_LOCALE_STRNG); jesper
If you sort an array of objects, the first variable in the object will be used for sorting: <?php class foo { var $value; //First variable: Used for sorting var $id; function foo($i, $v) { $this->id = $i; $this->value = $v; } } for ($i = 0; $i < 10; $i++) { $bar[] = new foo($i,rand(1,10)); } // This will sort on value sort($bar); print_r($bar); ?> Compare the piece of code above with the following: <?php class foo { var $id; //First variable: Used for sorting var $value; function foo($i, $v) { $this->id = $i; $this->value = $v; } } for ($i = 0; $i = 10; $i++) { $bar[] = new foo($i,rand(1,10)); } // This will sort on id sort($bar); print_r($bar); ?> As you can see the location of declaration of the variables matter! If you want to sort on both or on a combination of variables, use ksort() shailu_agrawal
if 2nd parameter is "SORT_REGULAR" it will compare characters by ASCII values. For ex: if unsorted values are: B , a , A with SORT_REGULAR sorted result will be: A , B , a and with SORT_STRING sorted result will be: a , A , B peek
I ran into the same problem with case insensitive sorting. Actually I think there should be a SORT_STRING_CASE flag but I tried the following: usort($listing, 'strcasecmp'); This didn't work (why not?), but you can do a proper case insensitive sort like this: usort($listing, create_function('$a,$b','return strcasecmp($a,$b);')); raul
I had an array like this: $arr=array (1,4,3,6,5); which returns this: $arr[0]=1 $arr[1]=4 $arr[2]=3 $arr[3]=6 $arr[4]=5 But lets say i remove [2] which is number 3, i get: $arr[0]=1 $arr[1]=4 $arr[3]=6 $arr[4]=5 And i want to reindex without doing a sort because i dont want to lose the order of the numbers (like a pop in a stack but in the middle of the list), i do this: $arr=array_chunk($arr,count($arr)); $arr=$arr[0]; the result is: $arr[0]=1 $arr[1]=4 $arr[2]=6 $arr[3]=5 This can be applied mostly for tree sorting, when you only have the id and the parent values of the node, and you want to have N levels. alishahnovin
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 */ ?> timc
I dig the multi_sort function(s) from above. But, they don't work for hash arrays. I added a keys variable to keep track of the key value as the array gets sorted. Feed back welcome. <?php function array_qsort (&$array, $column=0, $order=SORT_ASC, $first=0, $last= -2) { // $array - the array to be sorted // $column - index (column) on which to sort // can be a string if using an associative array // $order - SORT_ASC (default) for ascending or SORT_DESC for descending // $first - start index (row) for partial array sort // $last - stop index (row) for partial array sort // $keys - array of key values for hash array sort $keys = array_keys($array); if($last == -2) $last = count($array) - 1; if($last > $first) { $alpha = $first; $omega = $last; $key_alpha = $keys[$alpha]; $key_omega = $keys[$omega]; $guess = $array[$key_alpha][$column]; while($omega >= $alpha) { if($order == SORT_ASC) { while($array[$key_alpha][$column] < $guess) {$alpha++; $key_alpha = $keys[$alpha]; } while($array[$key_omega][$column] > $guess) {$omega--; $key_omega = $keys[$omega]; } } else { while($array[$key_alpha][$column] > $guess) {$alpha++; $key_alpha = $keys[$alpha]; } while($array[$key_omega][$column] < $guess) {$omega--; $key_omega = $keys[$omega]; } } if($alpha > $omega) break; $temporary = $array[$key_alpha]; $array[$key_alpha] = $array[$key_omega]; $alpha++; $key_alpha = $keys[$alpha]; $array[$key_omega] = $temporary; $omega--; $key_omega = $keys[$omega]; } array_qsort ($array, $column, $order, $first, $omega); array_qsort ($array, $column, $order, $alpha, $last); } } ?> qube#php@efnet
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). quirk
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; } ?> gerhard conradi
Hi @all, to my previous author: thanks, thanks, thanks! Works great and saved me lot of time. I added an extension for ascending/descending order. Here are the changes: // first i defined two constants for asc and desc // you can skip that, but then you have to change the switch command at the end of the function define("ORDER_ASC", "asc"); define("ORDER_DESC", "desc"); function mu_sort($array, $key_sort, $asc_desc) { // start function // check input parameters if (func_num_args()<2 || func_num_args()>3) die("Wrong number of parameters for the call of mu_sort()"); $array = func_get_arg(0); $key_sort = func_get_arg(1); if (func_num_args()==3) $asc_desc = func_get_arg(2); else $asc_desc = ORDER_ASC; $key_sorta = explode(",", $key_sort); .... // from here it's exactly the same ... // until here } // end loop #2 } // end loop #1 // sort // if you don't want to use the constants defined at the top, change here to whatever you're using switch($asc_desc) { case ORDER_DESC: rsort($output); break; default: sort($output); } // return sorted array return $output; } // end function Now you can call the function like this: mu_sort($array, $key_sort, ORDER_DESC); or even: mu_sort($array, $key_sort); // This will sort the array by default ascending Have fun... alishahnovin
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) */ ?> david wh thomas
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>'; ?> sinan
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 ) memzap
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]); dwatson
Here is a recursive use of sort for multi-dim arrays: <?php /*Mulsort function recursively sorts a multi-dimensional, numeric array in place, regardless of how many dimensions it has. The array can be ragged -- not a matrix. */ function mulsort(&$a) { sort($a); $c = count($a); for($i = 0; $i < $c; $i++) if (is_array($a[$i])) mulsort($a[$i]); } //The following array is just used to demo the mulsort function. $array_demo = array ( array ( array (333,1,9,8,7,6,5), array (array(1, 'x', 22), 99, 88 ), -10 ), array ( array (11, 12, 'a', 'b', 'c'), array (8, 1, 2,-5) ) ); echo "Array before sorting:<br /><pre>"; var_dump($array_demo); echo "</pre></ br></ br>"; mulsort($array_demo); echo "Array after sorting:<br /><pre>"; var_dump($array_demo); echo "</pre>"; ?> james
Further to john dot dutcher at highmark dot com's comments - padding the name could cause a problem if you get abnormally long names, it might be better to rebuild the array thus: Array ( [0] => Array ( [sortname_01] => Dutcher [sortname_02] => F [sortname_03] => John [name] => Dutcher, John F ) [1] => Array ( [sortname_01] => Dutch [sortname_02] => A [sortname_03] => Roger [name] => Dutch, Roger A ) [2] => Array ( [sortname_01] => Dut [sortname_02] => H [sortname_03] => Maurice [name] => Dut, Maurice H ) [3] => Array ( [sortname_01] => Dut [sortname_02] => S [sortname_03] => Mildred [name] => Dut, Mildred S ) ) which should give: Array ( [0] => Array ( [sortname_01] => Dut [sortname_02] => H [sortname_03] => Maurice [name] => Dut, Maurice H ) [1] => Array ( [sortname_01] => Dut [sortname_02] => S [sortname_03] => Mildred [name] => Dut, Mildred S ) [2] => Array ( [sortname_01] => Dutch [sortname_02] => A [sortname_03] => Roger [name] => Dutch, Roger A ) [3] => Array ( [sortname_01] => Dutcher [sortname_02] => F [sortname_03] => John [name] => Dutcher, John F ) ) phillip dot metzger
For a case insensitive sort use this array_multisort(). <?php $array_var = Array("Cheery", "zap", "Banana", "apple", "Zing"); array_multisort((strtolower($array_var)), SORT_ASC, SORT_STRING, $array_var); ?> Result order: apple Banana Cheery zap Zing whit
fmmarzoa's qsort_multiarray gets the last record with the removal of a "-1" from the 3rd line of the function definition. Here's a routine using it that takes a tab-delimited table with the column names in the first row, and displays it from an arbitrary column on the left to the last on the right with option to sort by any one column: <?php //tab-delimited ASCII file to sort - no more than one linefeed at end $infile="members.txt"; //first column on left to display - count from 0 $firstcol="1"; function qsort_multiarray($array, $num = 0, $order = "ASC", $left = 0, $right = -1) { if($right == -1) { $right = count($array); } $links = $left; $rechts = $right; $mitte = $array[($left + $right) / 2][$num]; if($rechts > $links) { do { if($order == "ASC") { while($array[$links][$num]<$mitte) $links++; while($array[$rechts][$num]>$mitte) $rechts--; } else { while($array[$links][$num]>$mitte) $links++; while($array[$rechts][$num]<$mitte) $rechts--; } if($links <= $rechts) { $tmp = $array[$links]; $array[$links++] = $array[$rechts]; $array[$rechts--] = $tmp; } } while($links <= $rechts); if ($left < $rechts) $array = qsort_multiarray($array,$num,$order,$left, $rechts); if ($links < $right) $array = qsort_multiarray($array,$num,$order,$links,$right); } return $array; } $mem=file("$infile"); $line=explode("\t","$mem[0]"); $cnt=count($line); echo "<html><head><title>$infile</title></head><body>"; echo "<table border=\"1\"><tr>"; for ($i=$firstcol;$i<$cnt;$i++) { echo "<td><a href=\"$PHP_SELF?col=$i\">$line[$i]</a></td>"; } echo "</tr>"; $cnt=count($mem); for ($i=$firstcol;$i<$cnt;$i++) { $line=explode("\t","$mem[$i]"); $cnt2=count($line); for ($j=$firstcol;$j<$cnt2;$j++) { $mem2[$i][$j]=$line[$j]; } } if(!isset($col)) $col=$firstcol; $mem2=qsort_multiarray($mem2,$col); for ($i=0;$i<$cnt;$i++) { echo "<tr>"; for ($j=$firstcol;$j<$cnt2;$j++) { $show=$mem2[$i][$j]; echo "<td>$show</td>"; } echo "</tr>"; } echo "</table></body></html>"; ?> nm
Faster, more effective function: array_sort (array, ['asc'/'desc']) Second parameter specifies whether to order ascending or descending. Default is ascending. function array_sort($array, $type='asc'){ $result=array(); foreach($array as $var => $val){ $set=false; foreach($result as $var2 => $val2){ if($set==false){ if($val>$val2 && $type=='desc' || $val<$val2 && $type=='asc'){ $temp=array(); foreach($result as $var3 => $val3){ if($var3==$var2) $set=true; if($set){ $temp[$var3]=$val3; unset($result[$var3]); } } $result[$var]=$val; foreach($temp as $var3 => $val3){ $result[$var3]=$val3; } } } } if(!$set){ $result[$var]=$val; } } return $result; } Works for ordering by integers or strings, no need to specify which. Example: $array=array('a' => 50, 'b' => 25, 'c' => 75); print_r(array_sort($array)); Returns: Array ( [b] => 25 [a] => 50 [c] => 75 ) joris
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. y5
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; } ludvig dot ericson
A tip for those who like "raul at jimi dot com dot mx" need to preserve keys after changing stuff in the middle of an array: array_values. Example: <?php $array = array(1, 2, 5, 9, 3); unset($array[3]); // Remove index 3, which is 9. $array = array_values($array); ?> Hint: array_values can be fine for removing keys and reindex them by number instead, too (applies to functions like posix_pwgetuid which returns an associative array, unlike C and others, call array_values on it, and it'll be the same format IIRC.) phpdotnetno_spam
/* Small function to Alphabetically sort Multidimensional arrays by index values of an n dimension array. I have only tested this for sorting an array of up to 6 dimensions by a value within the second dimension. This code is very rough and works for my purposes, but has not been tested beyond my needs. Although a little clunky and not a mathematical type algorithm, it get's the job done. It theoretically overcomes many of the problems I have seen with multidimensional arrays in that it is possible to specify within the function, not by reference :-(, which index you wish to sort by, no matter how many dimensions down. call function by assigning it to a new / existing array: $row_array = multidimsort($row_array); */ function multidimsort($array_in) { $multiarray = array(); $array_out = array(); $loopvalue = 0; /* -1 as traversal of array starts from 0, count() starts from 1 */ $multicount = count($array_in) - 1; /* add the indexes you wish to sort array by to a new array in this case index is two levels down, but shouldn't make a difference if it goes further indexes down. (Not tested!) */ for($i = 0; $i <= $multicount; $i++) { array_push($multiarray, $array_in[$i][2]); //array_push($multiarray, $array_in[$i][2][4]); //array_push($multiarray, $array_in[$i][1][3][7]); } /* alphabetically sort the new array (Ascending in this case) can chage sort to whatever type you like. Even apply user-defined sort. */ asort($multiarray); /* reset internal pointer to beginning of array after above sort */ reset($multiarray); /* traverse new array of index values and add the corresponding element of the input array to the correct position in the output array */ while (list ($key, $val) = each ($multiarray)) { $array_out[$loopvalue] = $array_in[$key]; $loopvalue++; } /* return the output array which is all nicely sorted by the index you wanted! */ return $array_out; } eran dot liberty
/** * 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 " $key => (" . $val['name'] . " ," . $val['age'] . ")"; } sortByFunc($arr,create_function('$element','return $element["age"];')); echo " now sorted:"; foreach($arr as $key => $val) { echo " $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) g8z
<?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; } ?> emiliyan
#This is a function that will sort an array... function sort_by($array, $keyname = null, $sortby) { $myarray = $inarray = array(); # First store the keyvalues in a seperate array foreach ($array as $i => $befree) { $myarray[$i] = $array[$i][$keyname]; } # Sort the new array by switch ($sortby) { case 'asc': # Sort an array and maintain index association... asort($myarray); break; case 'arsort': # Sort an array in reverse order and maintain index association arsort($myarray); break; case 'natcasesor': # Sort an array using a case insensitive "natural order" algorithm natcasesort($myarray); break; } # Rebuild the old array foreach ( $myarray as $key=> $befree) { $inarray[$key] = $array[$key]; } return $inarray; } sort_by(); example... $info = sort_by($myarray, 'name', $use = 'asc'); print_r($info); |
Change Languagearray_change_key_case array_chunk array_combine array_count_values array_diff_assoc array_diff_key array_diff_uassoc array_diff_ukey array_diff array_fill_keys array_fill array_filter array_flip array_intersect_assoc array_intersect_key array_intersect_uassoc array_intersect_ukey array_intersect array_key_exists array_keys array_map array_merge_recursive array_merge array_multisort array_pad array_pop array_product array_push array_rand array_reduce array_reverse array_search array_shift array_slice array_splice array_sum array_udiff_assoc array_udiff_uassoc array_udiff array_uintersect_assoc array_uintersect_uassoc array_uintersect array_unique array_unshift array_values array_walk_recursive array_walk array arsort asort compact count current each end extract in_array key krsort ksort list natcasesort natsort next pos prev range reset rsort shuffle sizeof sort uasort uksort usort |