Kebingungan dalam urutan penyortiran alami

Kebanyakan pengelola berkas grafis tidak mengurutkan secara leksikografis, melainkan menggunakan pengurutan "alami". Blok angka dalam nama diinterpretasikan sebagai angka—blok angka yang lebih besar menang, meskipun secara alfabetis berlaku sebaliknya. Ide di balik pengurutan alami: Yang biasanya diinginkan orang adalah "9 sebelum 10", "Bab 2 sebelum Bab 10"—tanpa harus menambahkan angka nol di depan.


Pasangan file berikut secara alami diurutkan dalam urutan menaik sebagai berikut:

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

Menakjubkan, tetapi dapat dijelaskan: Digit pertama \(9\) lebih kecil dari blok digit pertama \(950\) .

  • IMG_12113419_90.jpg
  • IMG_0554363070_90.jpg

Angka \(12113419\) lebih kecil dari \(554363070\) (angka \(0\) di depan dihilangkan).

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

Angka yang dibandingkan adalah \(0\) , \(2\) , \(3\) , \(10\) , \(12\) – tanda “-” tidak dianggap sebagai bagian dari angka tersebut.

Bahkan "alfabet" pun tidak ambigu secara global: Kapitalisasi, umlaut seperti ä (Jerman), atau huruf multi-karakter seperti ch (Ceko) menghasilkan varian yang valid. Oleh karena itu, "abjad murni" bergantung pada konteks. Windows Explorer mengimplementasikan hal ini dalam fungsi StrCmpLogicalW . Meskipun kode sumbernya (shlwapi.dll) bersifat hak milik dan tidak publik, terdapat implementasi ulang, misalnya, dari 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 lainnya menampilkan perilaku pengurutan yang serupa. Alat CLI seperti ls dan find Namun, pengurutannya berbeda dari pengelola berkas GUI. Semantik ada di nama berkas, bukan di API. Jika Anda menginginkan hasil yang akurat, tentukan konvensi: pemisah yang konsisten, angka yang diberi padding, dan penanganan satuan yang jelas. Dengan begitu, "abjad" akan kembali mudah ditebak.

Kembali