Zavar a természetes rendezési sorrendben

A legtöbb grafikus fájlkezelő nem szigorúan lexikográfiailag rendez, hanem „természetes” rendezést alkalmaz. A nevekben található számblokkokat számként értelmezi a rendszer – a nagyobb számblokk nyer, még akkor is, ha ábécérendben ennek az ellenkezője lenne igaz. A természetes rendezés mögötti ötlet: Az emberek általában azt szeretnék, hogy „9 legyen 10 előtt”, „2. fejezet a 10. fejezet előtt” – anélkül, hogy elöljáró nullákat kellene hozzáadni.


A következő fájlpárok természetesen növekvő sorrendben vannak rendezve az alábbiak szerint:

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

Elképesztő, de megmagyarázható: Az első számjegy \(9\) kisebb, mint az első számjegyblokk \(950\) .

  • IMG_12113419_90.jpg
  • IMG_0554363070_90.jpg

A \(12113419\) szám kisebb, mint \(554363070\) (a kezdő \(0\) eltávolítjuk).

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

Az összehasonlított számok a következők: \(0\) , \(2\) , \(3\) , \(10\) , \(12\) – a „-” nem tekinthető a szám részének.

Még az „ábécésorrendű” sem globálisan egyértelmű: a nagybetűs írásmód, az ékezetes betűk, mint például az ä (német), vagy a több karakterből álló betűk, mint a ch (cseh), legitim változatokhoz vezetnek. A „tisztán betűrendű” tehát kontextusfüggő. A Windows Intéző ezt a StrCmpLogicalW függvényben valósítja meg. Bár a forráskódja (shlwapi.dll) saját fejlesztésű és nem nyilvános, vannak újraimplementációi, például a ReactOS-ból.:

{
    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;
}

A Google Drive, a OneDrive, a KDE és más eszközök hasonló rendezési viselkedést mutatnak. A CLI eszközök, mint például a ls és find Azonban másképp rendeznek, mint a grafikus fájlkezelők. A szemantika a fájlnevekben van, nem az API-ban. Ha meglepetések nélküli eredményeket szeretnél, definiálj konvenciókat: következetes elválasztók, kitöltött számok és az egységek egyértelmű kezelése. Így az „ábécés” sorrend ismét kiszámíthatóvá válik.

Vissza