Сортировка массива имен папок, таких как Проводник Windows (числовые и по алфавиту) - VB.NET

Я убиваю себя и обезвоживаю, пытаясь отсортировать этот массив.

У меня есть массив, содержащий каталоги, созданные с помощью

Dim Folders() As String = Directory.GetDirectories(RootPath)

Мне нужно, чтобы они были отсортированы так, чтобы они выглядели как в Windows Explorer в win7/vista. - в цифровом и алфавитном порядке именами папок.

Имена папок содержат как буквы, так и цифры, иногда только буквы или цифры.

Простой массив Array.Sort(Folders) приводит к

C:\inetpub\wwwroot\rootpath\1
C:\inetpub\wwwroot\rootpath\10
C:\inetpub\wwwroot\rootpath\100
C:\inetpub\wwwroot\rootpath\1004
C:\inetpub\wwwroot\rootpath\101
C:\inetpub\wwwroot\rootpath\11
C:\inetpub\wwwroot\rootpath\12
C:\inetpub\wwwroot\rootpath\2
C:\inetpub\wwwroot\rootpath\3
C:\inetpub\wwwroot\rootpath\4
C:\inetpub\wwwroot\rootpath\5
C:\inetpub\wwwroot\rootpath\6
C:\inetpub\wwwroot\rootpath\7
C:\inetpub\wwwroot\rootpath\8
C:\inetpub\wwwroot\rootpath\87skjnd
C:\inetpub\wwwroot\rootpath\89sdf93kmw3
C:\inetpub\wwwroot\rootpath\9
C:\inetpub\wwwroot\rootpath\ad
C:\inetpub\wwwroot\rootpath\bin
C:\inetpub\wwwroot\rootpath\dark
C:\inetpub\wwwroot\rootpath\erk
C:\inetpub\wwwroot\rootpath\jkh23978yoaslkd3
C:\inetpub\wwwroot\rootpath\lk2309as
C:\inetpub\wwwroot\rootpath\work
C:\inetpub\wwwroot\rootpath\zone

Что я хочу иметь (и что отображается в проводнике Windows)...

C:\inetpub\wwwroot\rootpath\1
C:\inetpub\wwwroot\rootpath\2
C:\inetpub\wwwroot\rootpath\3
C:\inetpub\wwwroot\rootpath\4
C:\inetpub\wwwroot\rootpath\5
C:\inetpub\wwwroot\rootpath\6
C:\inetpub\wwwroot\rootpath\7
C:\inetpub\wwwroot\rootpath\8
C:\inetpub\wwwroot\rootpath\9
C:\inetpub\wwwroot\rootpath\10
C:\inetpub\wwwroot\rootpath\11
C:\inetpub\wwwroot\rootpath\12
C:\inetpub\wwwroot\rootpath\87skjnd
C:\inetpub\wwwroot\rootpath\89sdf93kmw3
C:\inetpub\wwwroot\rootpath\100
C:\inetpub\wwwroot\rootpath\101
C:\inetpub\wwwroot\rootpath\1004
C:\inetpub\wwwroot\rootpath\ad
C:\inetpub\wwwroot\rootpath\bin
C:\inetpub\wwwroot\rootpath\dark
C:\inetpub\wwwroot\rootpath\erk
C:\inetpub\wwwroot\rootpath\jkh23978yoaslkd3
C:\inetpub\wwwroot\rootpath\lk2309as
C:\inetpub\wwwroot\rootpath\work
C:\inetpub\wwwroot\rootpath\zone

Я googled и узнал, что класс должен быть написан, который использует IComparable для сортировки элементов. Быть супернейшей... Я действительно не знаю, как это можно сделать. В большинстве примеров, на которые я смотрел, были многомерные массивы и ключи: S...

будет еще лучше, если сортировка может быть применена к массиву имен файлов (вместо имен папок) или массиву, содержащему обе папки и файлы... в этом случае отсортированные папки отображаются вверху и отсортированные файлы ниже.. это даже возможно?

Любая помощь будет очень полезна...: D спасибо.

Ответ 1

Вам понадобится реализовать IComparer, а не создавать класс, который реализует IComparable. Разница в том, что IComparer имеет необходимое "знание" для сравнения двух объектов, тогда как IComparable реализуется классом, который знает, как сравнивать себя с чем-то другим.

И способ, которым Windows Explorer сортирует имена файлов, использует функцию StrCmpLogicalW. Вы можете использовать эту функцию в своем собственном IComparer, чтобы получить то же поведение, что и проводник Windows. Эта функция обрабатывает числовые части строк как числа так, чтобы 9 сортировок до 10.

public class MyComparer : IComparer<string> {

    [DllImport("shlwapi.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
    static extern int StrCmpLogicalW(String x, String y);

    public int Compare(string x, string y) {
        return StrCmpLogicalW(x, y);
    }

}

Array.Sort(unsortedNames, new MyComparer());

И так как я только заметил, что вопрос отмечен VB... Простите мой ржавый VB!

Public Class MyComparer
    Implements IComparer(Of String)

    Declare Unicode Function StrCmpLogicalW Lib "shlwapi.dll" ( _
        ByVal s1 As String, _
        ByVal s2 As String) As Int32

    Public Function Compare(Byval x as String, Byval y as String) As Integer _
        Implements System.Collections.Generic.IComparer(Of String).Compare

        Return StrCmpLogicalW(x, y)

    End Function

End Class

Ответ 2

Array.Sort также имеет параметр IComparer, вы можете переопределить поведение сортировки, если вам не нравится значение по умолчанию. см. Array.Sort Method (T [], IComparer) как это сделать