Confusion dans l'ordre de tri naturel

La plupart des gestionnaires de fichiers graphiques ne trient pas strictement de manière lexicographique, mais utilisent plutôt un tri « naturel ». Les blocs de nombres dans les noms sont interprétés comme des nombres ; le bloc de nombres le plus grand l'emporte, même si l'inverse est vrai alphabétiquement. L'idée derrière le tri naturel : ce que l'on recherche généralement, c'est « 9 avant 10 », « Chapitre 2 avant Chapitre 10 », sans avoir à ajouter de zéros non significatifs.


Les paires de fichiers suivantes sont naturellement triées par ordre croissant comme suit:

  • build-9e2.log
  • build-950.log

Étonnant, mais explicable : le premier chiffre \(9\) est plus petit que le premier bloc de chiffres \(950\) .

  • IMG_12113419_90.jpg
  • IMG_0554363070_90.jpg

Le nombre \(12113419\) est inférieur à \(554363070\) (le \(0\) initial est supprimé).

  • temp_0C.txt
  • temp_2C.txt
  • temp_-3C.txt
  • temp_10C.txt
  • temp_-12C.txt

Les nombres comparés sont \(0\) , \(2\) , \(3\) , \(10\) , \(12\) – le « - » n’est pas considéré comme faisant partie du nombre.

Même le terme « alphabétique » n'est pas universellement univoque : les majuscules, les trémas comme ä (allemand) ou les lettres à plusieurs caractères comme ch (tchèque) donnent lieu à des variantes légitimes. Le terme « purement alphabétique » dépend donc du contexte. L'Explorateur Windows implémente cette fonction dans la fonction StrCmpLogicalW . Bien que son code source (shlwapi.dll) soit propriétaire et non public, il existe des réimplémentations, par exemple issues de ReactOS.:

{
    TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp));
 
    if (!str || !comp)
        return 0;
 
    while (*str)
    {
        if (!*comp)
            return 1;
        else if (*str >= '0' && *str <= '9')
        {
            int str_value, comp_value;
 
            if (*comp < '0' || *comp > '9')
                return -1;
 
            /* Compare the numbers */
            StrToIntExW(str, 0, &str_value);
            StrToIntExW(comp, 0, &comp_value);
 
            if (str_value < comp_value)
                return -1;
            else if (str_value > comp_value)
                return 1;
 
            /* Skip */
            while (*str >= '0' && *str <= '9') str++;
            while (*comp >= '0' && *comp <= '9') comp++;
        }
        else if (*comp >= '0' && *comp <= '9')
            return 1;
        else
        {
            int diff = ChrCmpIW(*str, *comp);
            if (diff > 0)
                return 1;
            else if (diff < 0)
                return -1;
 
            str++;
            comp++;
        }
    }
 
    if (*comp)
      return -1;
 
    return 0;
}

Google Drive, OneDrive, KDE et d'autres affichent un comportement de tri similaire. Les outils CLI comme ls et find Cependant, leur tri est différent de celui des gestionnaires de fichiers à interface graphique. La sémantique se trouve dans les noms de fichiers, et non dans l'API. Pour des résultats sans surprise, définissez des conventions : séparateurs cohérents, nombres complétés et gestion claire des unités. Le système « alphabétique » redevient alors prévisible.

Retour