Kekeliruan dalam susunan pengisihan semula jadi

Kebanyakan pengurus fail grafik tidak mengisih secara ketat secara leksikografi, tetapi menggunakan pengisihan "semula jadi". Blok nombor dalam nama ditafsirkan sebagai nombor-blok nombor yang lebih besar menang, walaupun sebaliknya adalah benar mengikut abjad. Idea di sebalik pengisihan semula jadi: Perkara yang biasanya dikehendaki orang ialah "9 sebelum 10," "Bab 2 sebelum Bab 10"—tanpa perlu menambah sifar pendahuluan.


Pasangan fail berikut disusun secara semula jadi dalam tertib menaik seperti berikut:

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

Hebat, tetapi boleh dijelaskan: Digit pertama \(9\) adalah lebih kecil daripada blok pertama digit \(950\) .

  • IMG_12113419_90.jpg
  • IMG_0554363070_90.jpg

Nombor \(12113419\) adalah kurang daripada \(554363070\) (tanda hadapan \(0\) dialih keluar).

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

Nombor yang dibandingkan ialah \(0\) , \(2\) , \(3\) , \(10\) , \(12\) – “-” tidak dianggap sebagai sebahagian daripada nombor itu.

Malah "abjad" tidak jelas secara global: Huruf besar, umlaut seperti ä (Jerman), atau huruf berbilang aksara seperti ch (Czech) membawa kepada varian yang sah. Oleh itu, "Semata-mata abjad" bergantung kepada konteks. Windows Explorer melaksanakan ini dalam fungsi StrCmpLogicalW . Walaupun kod sumbernya (shlwapi.dll) adalah proprietari dan bukan awam, terdapat pelaksanaan semula, contohnya, daripada 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 dan lain-lain memaparkan gelagat pengisihan yang serupa. Alat CLI seperti ls dan find Walau bagaimanapun, mereka menyusun secara berbeza daripada pengurus fail GUI. Semantik adalah dalam nama fail, bukan dalam API. Jika anda mahukan hasil tanpa kejutan, tentukan konvensyen: pemisah yang konsisten, nombor berlapik dan pengendalian unit yang jelas. Kemudian "abjad" menjadi boleh diramal semula.

Belakang