PHP 5.4.31 Released

natsort

(PHP 4, PHP 5)

natsortTrie un tableau avec l'algorithme à "ordre naturel"

Description

bool natsort ( array &$array )

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 ou FALSE si une erreur survient.

Historique

Version Description
5.2.10 Les chaines numériques alignées par des zéros (e.g., '00005') ignorent les zéros d'alignement.

Exemples

Exemple #1 Exemple d'utilisation de base avec natsort()

<?php
$array1 
$array2 = array("img12.png""img10.png""img2.png""img1.png");

asort($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
(
    [3] => img1.png
    [1] => img10.png
    [0] => img12.png
    [2] => 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 sur » la comparaison de chaînes en ordre naturel.

Exemple #2 Exemples montrant les pièges de natsort()

<?php
echo "Nombres négatifs\n";
$negative = array('-5','3','-2','0','-1000','9','1');
print_r($negative);
natsort($negative);
print_r($negative);

echo 
"Alignement avec zéros\n";
$zeros = array('09''8''10''009''011''0'); 
print_r($zeros);
natsort($zeros);
print_r($zeros);

echo 
"Autres caractères pouvant interférer\n";
$images_oops = array('image_1.jpg','image_12.jpg''image_21.jpg''image_4.jpg');
print_r($images_oops);
natsort($images_oops);
print_r($images_oops);

echo 
"Tri par clés\n";
$smoothie = array('orange' => 1'apple' => 1'yogurt' => 4'banana' => 4);
print_r($smoothie);
uksort$smoothie'strnatcmp');
print_r($smoothie);
?>

L'exemple ci-dessus va afficher :

Nombres négatifs
Array
(
    [0] => -5
    [1] => 3
    [2] => -2
    [3] => 0
    [4] => -1000
    [5] => 9
    [6] => 1
)
Array
(
    [2] => -2
    [0] => -5
    [4] => -1000
    [3] => 0
    [6] => 1
    [1] => 3
    [5] => 9
)

Alignement avec zéros
Array
(
    [0] => 09
    [1] => 8
    [2] => 10
    [3] => 009
    [4] => 011
    [5] => 0
)
Array
(
    [5] => 0
    [1] => 8
    [3] => 009
    [0] => 09
    [2] => 10
    [4] => 011
)

Autres caractères pouvant interférer
Array
(
    [0] => image_1.jpg
    [1] => image_12.jpg
    [2] => image_21.jpg
    [3] => image_4.jpg
)
Array
(
    [0] => image_1.jpg
    [3] => image_4.jpg
    [1] => image_12.jpg
    [2] => image_21.jpg
)

Tri par clés
Array
(
    [orange] => 1
    [apple]  => 1
    [yogurt] => 4
    [banana] => 4
)
Array
(
    [apple]  => 1
    [banana] => 4
    [orange] => 1
    [yogurt] => 4
)

Voir aussi

  • natcasesort() - Trie un tableau avec l'algorithme à "ordre naturel" insensible à la casse
  • Les fonctions de tri des tableaux
  • strnatcmp() - Comparaison de chaînes avec l'algorithme d'"ordre naturel"
  • strnatcasecmp() - Comparaison de chaînes avec l'algorithme d'"ordre naturel" (insensible à la casse)

add a note add a note

User Contributed Notes 18 notes

up
9
Johan GENNESSON (php at genjo dot fr)
3 years ago
Be careful of the new behaviour in 5.2.10 version.
See the following sample:

<?php

$array
= array('1 bis', '10 ter', '0 PHP', '0', '01', '01 Ver', '0 ', '1 ', '1');

natsort($array);
echo
'<pre>';
print_r($array);
echo
'</pre>';
?>

5.2.6-1 will output:
Array
(
    [3] => 0
    [6] => 0
    [2] => 0 OP
    [4] => 01
    [5] => 01 Ver
    [8] => 1
    [7] => 1
    [0] => 1 bis
    [1] => 10 ter
)

5.2.10 will output:
Array
(
    [6] => 0
    [3] => 0
    [8] => 1
    [4] => 01
    [7] => 1
    [5] => 01 Ver
    [0] => 1 bis
    [1] => 10 ter
    [2] => 0 OP
)

Greetings
up
4
h3
8 years ago
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'
up
5
flash at minet dot net
10 years ago
About the reverse natsort.. Maybe simpler to do :

function strrnatcmp ($a, $b) {
    return strnatcmp ($b, $a);
}
up
4
xlab AT adaptiveNOSPAMarts DOT net
10 years ago
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.
up
2
Christoph
4 years ago
Note:

The natsort function will sort depending on the operating system, but not depending on either Linux or Windows-based systems

There's a difference when sorting an array which is generated from the filesystem:
Array(
    [0] => ./system/kernel/js/01_ui.core.js
    [1] => ./system/kernel/js/00_jquery-1.3.2.js
    [2] => ./system/kernel/js/02_my.desktop.js
)

natsort($array) will result in two different ways:

Case 1: (Debian)
Array(
    [1] => ./system/kernel/js/00_jquery-1.3.2.js
    [0] => ./system/kernel/js/01_ui.core.js
    [2] => ./system/kernel/js/02_my.desktop.js
)

Case 2: (Debian Kernel, but Ubuntu shadowed php-Version)
Array(
    [0] => ./system/kernel/js/01_ui.core.js
    [2] => ./system/kernel/js/02_my.desktop.js
    [1] => ./system/kernel/js/00_jquery-1.3.2.js
)

...so make sure you've named the files beginning with 01, then it works fine.
up
1
wyvern at greywyvern dot com
5 years ago
There's no need to include your own API code to natsort an associative array by key.  PHP's in-built functions (other than natsort) can do the job just fine:

<?php
  uksort
($myArray, "strnatcmp");
?>
up
0
ale152
5 years ago
Note: negatives number.
<?php
$a
= array(-5,-2,3,9);
natsort($a);
print_r($a);
?>
Will output:
Array ( [1] => -2 [0] => -5 [2] => 3 [3] => 9 )
up
0
AJenbo
5 years ago
natsort might not act like you would expect with zero padding, heres a quick sample.

<?php
$array
= array('09', '8', '10', '009', '011');
natsort($array);
?>
/*
Array
(
    [3] => 009
    [4] => 011
    [0] => 09
    [1] => 8
    [2] => 10
)
*/
up
0
lacent at gmail dot com
7 years ago
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;
    }
up
0
@gmail bereikme
7 years ago
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
up
0
Anonymous
8 years ago
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( ).
up
0
lil at thedreamersmaze dot spam-me-not dot org
8 years ago
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;
}

?>
up
0
natcasesort.too
8 years ago
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!
up
0
phpnet at moritz-abraham dot de
9 years ago
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;
}
?>
up
0
mbirth at webwriters dot de
10 years ago
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;
}

?>
up
0
rasmus at flajm dot com
10 years ago
To make a reverse function, you can simply:

function rnatsort(&$a){
    natsort($a);
    $a = array_reverse($a, true);
}
up
0
justin at redwiredesign dot com
10 years ago
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;
}
up
-1
anonymous at coward dot net
11 years ago
Reverse Natsort:

  function rnatsort($a, $b) {
    return -1 * strnatcmp($a, $b);
  }

  usort($arr, "rnatsort");
To Top