Here is a natsort that will sort the array based on keys (it is similar to the function posted earlier on 04-May-2006).
<?php
function knatsort(&$karr){
$kkeyarr = array_keys($karr);
natsort($kkeyarr);
$ksortedarr = array();
foreach($kkeyarr as $kcurrkey){
$ksortedarr[$kcurrkey] = $karr[$kcurrkey];
}
$karr = $ksortedarr;
return true;
}
?>
natsort
(PHP 4, PHP 5)
natsort — Trie un tableau avec l'algorithme à "ordre naturel"
Description
natsort() implémente un algorithme de tri qui traite les chaînes alphanumériques du tableau array comme un être humain tout en conservant la relation clé/valeur. C'est ce qui est appelé l'"ordre naturel". Un exemple de la différence de traitement entre un tel algorithme et un algorithme de tri de chaînes (comme lorsqu'on utilise sort()) est illustré ci-dessous.
Liste de paramètres
- array
-
Le tableau d'entrée.
Valeurs de retour
Cette fonction retourne TRUE en cas de succès, FALSE en cas d'échec.
Exemples
Exemple #1 Exemple avec natsort()
<?php
$array1 = $array2 = array("img12.png", "img10.png", "img2.png", "img1.png");
sort($array1);
echo "Standard sorting\n";
print_r($array1);
natsort($array2);
echo "\nNatural order sorting\n";
print_r($array2);
?>
L'exemple ci-dessus va afficher :
Standard sorting Array ( [0] => img1.png [1] => img10.png [2] => img12.png [3] => img2.png ) Natural order sorting Array ( [3] => img1.png [2] => img2.png [1] => img10.png [0] => img12.png )
Pour plus de détails, rendez-vous sur le site de Martin Pool : » Natural Order String Comparison.
natsort
16-Jun-2008 02:03
30-Aug-2007 09:34
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');
16-Jan-2007 06:42
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;
}
01-Sep-2006 05:06
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
04-May-2006 04:50
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
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( ).
22-Feb-2006 05:59
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'
31-Jan-2006 05:38
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;
}
?>
05-Aug-2005 12:17
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!
28-Jun-2005 06:08
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;
}
?>
02-Sep-2004 11:09
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;
}
?>
15-Jan-2004 09:51
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.
09-Jan-2004 09:31
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;
}
?>
15-Dec-2003 06:30
To make a reverse function, you can simply:
function rnatsort(&$a){
natsort($a);
$a = array_reverse($a, true);
}
22-Aug-2003 07:10
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;
}
12-Aug-2003 07:27
About the reverse natsort.. Maybe simpler to do :
function strrnatcmp ($a, $b) {
return strnatcmp ($b, $a);
}
03-Jun-2003 03:41
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);
31-May-2003 10:46
Reverse Natsort:
function rnatsort($a, $b) {
return -1 * strnatcmp($a, $b);
}
usort($arr, "rnatsort");
