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 le « tri naturel ». Les blocs de chiffres dans le nom sont interprétés comme des nombres - le bloc de chiffres le plus grand l'emporte, même si le contraire apparaît en termes purement alphabétiques. L'idée derrière le tri naturel : ce que les gens veulent le plus, c'est « 9 avant 10 », « Chapitre 2 avant le 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

Étonnamment, mais explicable : le premier bloc de chiffres \(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 les services similaires présentent un comportement de tri comparable. Les outils en ligne de commande comme… ls et find trier différemment des gestionnaires de fichiers GUI. La sémantique est dans les noms de fichiers, pas dans l'API. Si vous voulez des résultats sans surprise, définissez des conventions : des séparateurs cohérents, des nombres remplis et une gestion claire des unités. Alors « alphabétique » redevient prévisible.

Retour