Confuzie în ordinea naturală de sortare

Majoritatea managerilor de fișiere grafice nu sortează strict lexicografic, ci folosesc sortarea „naturală”. Blocurile de numere din nume sunt interpretate ca numere - blocul mai mare de numere câștigă, chiar dacă opusul ar fi valabil alfabetic. Ideea din spatele sortării naturale: Ceea ce oamenii își doresc de obicei este „9 înainte de 10”, „Capitolul 2 înainte de Capitolul 10” - fără a fi nevoie să adauge zerouri la început.


Următoarele perechi de fișiere sunt sortate în mod natural în ordine crescătoare, după cum urmează:

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

Uimitor, dar explicabil: Prima cifră \(9\) este mai mică decât primul bloc de cifre \(950\) .

  • IMG_12113419_90.jpg
  • IMG_0554363070_90.jpg

Numărul \(12113419\) este mai mic decât \(554363070\) ( \(0\) ul inițial este eliminat).

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

Numerele comparate sunt \(0\) , \(2\) , \(3\) , \(10\) , \(12\) – „-” nu este considerat parte a numărului.

Chiar și „alfabetic” nu este global lipsit de ambiguitate: majusculele, umlautele precum ä (germană) sau literele cu mai multe caractere precum ch (cehă) duc la variante legitime. Prin urmare, „pur alfabetic” depinde de context. Windows Explorer implementează acest lucru în funcția StrCmpLogicalW . Deși codul sursă (shlwapi.dll) este proprietar și nu public, există reimplementări, de exemplu, de la 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 și altele afișează un comportament de sortare similar. Instrumente CLI precum ls și find Totuși, acestea sortează diferit față de managerii de fișiere GUI. Semantica se află în numele fișierelor, nu în API. Dacă doriți rezultate fără surprize, definiți convenții: separatoare consecvente, numere umplute și gestionarea clară a unităților. Atunci „alfabetic” devine din nou previzibil.

Înapoi