|
natsort
Sort an array using a "natural order" algorithm
(PHP 4, PHP 5)
Example 316. natsort() example<?php The above example will output: Standard sorting For more information see: Martin Pool's » Natural Order String Comparison page. Related Examples ( Source code ) » natsort Examples ( Source code ) » Create a swf slideshow Code Examples / Notes » natsortxlab
Under limited testing, natsort() appears to work well for IP addresses. For my needs, it is far less code than the ip2long()/long2ip() conversion I was using before.
rasmus
To make a reverse function, you can simply: function rnatsort(&$a){ natsort($a); $a = array_reverse($a, true); } h3
This function can be very usefull, but in some cases, like if you want to sort a MySQL query result, it's important to keep in mind that MySQL as built'in sorting functions which are way faster than resorting the result using a complex php algorythm, especially with large arrays. ex; 'SELECT * FROM `table` ORDER BY columnName ASC, columnName2 DESC' lil
There's one little thing missing in this useful bit of code posted by mbirth at webwriters dot de: <?php function natsort2d(&$aryInput) { $aryTemp = $aryOut = array(); foreach ($aryInput as $key=>$value) { reset($value); $aryTemp[$key]=current($value); } natsort($aryTemp); foreach ($aryTemp as $key=>$value) { $aryOut[$key] = $aryInput[$key]; // --------^^^^ add this if you want your keys preserved! } $aryInput = $aryOut; } ?> lacent
there is another rnatsort function lower on the page, but it didn't work in the context i needed it in. reasoning for this: sorting naturally via the keys of an array, but needing to reverse the order. function rnatsort ( &$array = array() ) { $keys = array_keys($array); natsort($keys); $total = count($keys) - 1; $temp1 = array(); $temp2 = array(); // assigning original keys to an array with a backwards set of keys, to use in krsort(); foreach ( $keys as $key ) { $temp1[$total] = $key; --$total; } ksort($temp1); // setting the new array, with the order from the krsort() and the values of original array. foreach ( $temp1 as $key ) { $temp2[$key] = $array[$key]; } $array = $temp2; } 12-mar-2006 03:44
The last comment should have been posted in doc about (r)sort( ). Indeed, and unfortunately, ORDER BY *does not* perform natural ordering. So, sometimes we *must* do a SQL request followed by natsort( ).
dslicer
Something that should probably be documented is the fact that both natsort and natcasesort maintain the key-value associations of the array. If you natsort a numerically indexed array, a for loop will not produce the sorted order; a foreach loop, however, will produce the sorted order, but the indices won't be in numeric order. If you want natsort and natcasesort to break the key-value associations, just use array_values on the sorted array, like so: natsort($arr); $arr = array_values($arr); anonymous
Reverse Natsort: function rnatsort($a, $b) { return -1 * strnatcmp($a, $b); } usort($arr, "rnatsort"); justin
One of the things I've needed to do lately is apply natural sorting to a complex array, e.g.: Array ( [0] => Array ( [ID] = 4 [name] = Fred ) [1] => Array ( [ID] = 6 [name] = Bob ) ) where I want to sort the parent array by the child's name. I couldn't see a way of doing this using array_walk, so I've written a simple function to do it. Hopefully someone will find this useful: /** * @return Returns the array sorted as required * @param $aryData Array containing data to sort * @param $strIndex Name of column to use as an index * @param $strSortBy Column to sort the array by * @param $strSortType String containing either asc or desc [default to asc] * @desc Naturally sorts an array using by the column $strSortBy */ function array_natsort($aryData, $strIndex, $strSortBy, $strSortType=false) { // if the parameters are invalid if (!is_array($aryData) || !$strIndex || !$strSortBy) // return the array return $aryData; // create our temporary arrays $arySort = $aryResult = array(); // loop through the array foreach ($aryData as $aryRow) // set up the value in the array $arySort[$aryRow[$strIndex]] = $aryRow[$strSortBy]; // apply the natural sort natsort($arySort); // if the sort type is descending if ($strSortType=="desc") // reverse the array arsort($arySort); // loop through the sorted and original data foreach ($arySort as $arySortKey => $arySorted) foreach ($aryData as $aryOriginal) // if the key matches if ($aryOriginal[$strIndex]==$arySortKey) // add it to the output array array_push($aryResult, $aryOriginal); // return the return return $aryResult; } awizemann
natsort() will not work correctly if you use underscores in file names (if your array is for sorting files). Example: $images = array('image_1.jpg','image_12.jpg'); Will not produce the same as: $images = array('image1.jpg','image12.jpg'); natcasesort.too
I got caught out through naive use of this feature - attempting to sort a list of image filenames from a digital camera, where the filenames are leading zero padded (e.g. DSCF0120.jpg) , will not sort correctly. Maybe the example could be modified to exhibit this behaviour (e.g. set array to -img0120.jpg','IMG0.png', 'img0012.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png) If the example hadn't used images I would have coded it correctly first time around! mroach
Here's an expansion of the natsort2d function that mbirth wrote. This one allows you to specify the key for sorting. <?php function natsort2d( &$arrIn, $index = null ) { $arrTemp = array(); $arrOut = array(); foreach ( $arrIn as $key=>$value ) { reset($value); $arrTemp[$key] = is_null($index) ? current($value) : $value[$index]; } natsort($arrTemp); foreach ( $arrTemp as $key=>$value ) { $arrOut[$key] = $arrIn[$key]; } $arrIn = $arrOut; } ?> @gmail bereikme
Here's a handy function to sort an array on 1 or more columns using natural sort: <?php // Example: $records = columnSort($records, array('name', 'asc', 'addres', 'desc', 'city', 'asc')); $globalMultisortVar = array(); function columnSort($recs, $cols) { global $globalMultisortVar; $globalMultisortVar = $cols; usort($recs, 'multiStrnatcmp'); return($recs); } function multiStrnatcmp($a, $b) { global $globalMultisortVar; $cols = $globalMultisortVar; $i = 0; $result = 0; while ($result == 0 && $i < count($cols)) { $result = ($cols[$i + 1] == 'desc' ? strnatcmp($b[$cols[$i]], $a[$cols[$i]]) : $result = strnatcmp($a[$cols[$i]], $b[$cols[$i]])); $i+=2; } return $result; } ?> Greetings, - John nissar_pa
Here is the program which will sort an array key in natural order and maintains key to data correlations function natSortKey(&$arrIn) { $key_array = array(); $arrOut = array(); foreach ( $arrIn as $key=>$value ) { $key_array[]=$key; } natsort( $key_array); foreach ( $key_array as $key=>$value ) { $arrOut[$value]=$arrIn[$value]; } $arrIn=$arrOut; } Thanks, Abdul Nissar mbirth
For those who want to natsort a 2d-array on the first element of each sub-array, the following few lines should do the job. <?php function natsort2d(&$aryInput) { $aryTemp = $aryOut = array(); foreach ($aryInput as $key=>$value) { reset($value); $aryTemp[$key]=current($value); } natsort($aryTemp); foreach ($aryTemp as $key=>$value) { $aryOut[] = $aryInput[$key]; } $aryInput = $aryOut; } ?> phpnet
additional to the code posted by justin at redwiredesign dot com (which I found very usefull) here is a function that sorts complex arrays like this: <? $array['test0'] = array('main' => 'a', 'sub' => 'a'); $array['test2'] = array('main' => 'a', 'sub' => 'b'); $array['test3'] = array('main' => 'b', 'sub' => 'c'); $array['test1'] = array('main' => 'a', 'sub' => 'c'); $array['test4'] = array('main' => 'b', 'sub' => 'a'); $array['test5'] = array('main' => 'b', 'sub' => 'b'); ?> or <? $array[0] = array('main' => 1, 'sub' => 1); $array[2] = array('main' => 1, 'sub' => 2); $array[3] = array('main' => 2, 'sub' => 3); $array[1] = array('main' => 1, 'sub' => 3); $array[4] = array('main' => 2, 'sub' => 1); $array[5] = array('main' => 2, 'sub' => 2); ?> on one or more columns. the code <? $array = array_natsort_list($array,'main','sub'); ?> will result in $array being sortet like this: test0,test2,test1,test4,test5,test3 or 0,2,1,4,5,3. you may even submit more values to the function as it uses a variable parameter list. the function starts sorting on the last and the goes on until the first sorting column is reached. to me it was very usefull for sorting a menu having submenus and even sub-submenus. i hope it might help you too. here is the function: <? function array_natsort_list($array) { // for all arguments without the first starting at end of list for ($i=func_num_args();$i>1;$i--) { // get column to sort by $sort_by = func_get_arg($i-1); // clear arrays $new_array = array(); $temporary_array = array(); // walk through original array foreach($array as $original_key => $original_value) { // and save only values $temporary_array[] = $original_value[$sort_by]; } // sort array on values natsort($temporary_array); // delete double values $temporary_array = array_unique($temporary_array); // walk through temporary array foreach($temporary_array as $temporary_value) { // walk through original array foreach($array as $original_key => $original_value) { // and search for entries having the right value if($temporary_value == $original_value[$sort_by]) { // save in new array $new_array[$original_key] = $original_value; } } } // update original array $array = $new_array; } return $array; } ?> flash
About the reverse natsort.. Maybe simpler to do : function strrnatcmp ($a, $b) { return strnatcmp ($b, $a); } |
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 |