#vb.net #sorting
#vb.net #сортировка
Вопрос:
Приведенный ниже код используется для сортировки каталогов в vb.net .
Dim a As New List(Of String)
a.Add("abc")
a.Add("abcd")
a.Add("abc d")
a.Add("abc de")
a.Add("abcdf")
a.Sort(Function(x, Y) (x).CompareTo((Y)))
Результат:
abc
abc d
abc de
abcd
abcdf
В результирующем списке каталоги с пробелом помещаются перед «».
Существует более 1500000 подкаталогов и файлов, на сортировку которых уходит около 50 секунд (метод по умолчанию). Все другие методы, которые мы пробовали, занимают не менее 400 секунд.
как отсортировать путь к каталогу по алфавиту? Есть ли какой-либо встроенный метод для учета обратной косой черты перед пробелом?
Ответ №1:
Вам нужно разбить путь на отдельные названия папок и сравнивать каждое из них по очереди, пока не найдете разницу. Если разницы нет, то вы используете длину для различения, т. Е. папка более высокого уровня идет первой.
a.Sort(Function(x, y)
Dim xFolderNames As New List(Of String)
Dim yFolderNames As New List(Of String)
'Split first path into folder names.
Do Until String.IsNullOrEmpty(x)
xFolderNames.Insert(0, Path.GetFileName(x))
x = Path.GetDirectoryName(x)
Loop
'Split second path into folder names.
Do Until String.IsNullOrEmpty(y)
yFolderNames.Insert(0, Path.GetFileName(y))
y = Path.GetDirectoryName(y)
Loop
Dim result = 0
'Compare up to as many folders as are in the shortest path.
For i = 0 To Math.Min(xFolderNames.Count, yFolderNames.Count) - 1
result = xFolderNames(i).CompareTo(yFolderNames(i))
If result <> 0 Then
'A difference has been found.
Exit For
End If
Next
If result = 0 Then
'No difference was found so put the shortest path first.
result = xFolderNames.Count.CompareTo(yFolderNames.Count)
End If
Return result
End Function)
Для наглядности вот класс, который инкапсулирует эту функциональность:
Imports System.Collections.ObjectModel
Imports System.IO
Public Class FileSystemPath
Implements IComparable, IComparable(Of FileSystemPath)
Public ReadOnly Property FullPath As String
Public ReadOnly Property PartialPaths As ReadOnlyCollection(Of String)
Public Sub New(fileOrFolderPath As String)
FullPath = fileOrFolderPath
Dim partialPaths As New List(Of String)
Do Until String.IsNullOrEmpty(fileOrFolderPath)
partialPaths.Insert(0, Path.GetFileName(fileOrFolderPath))
fileOrFolderPath = Path.GetDirectoryName(fileOrFolderPath)
Loop
Me.PartialPaths = New ReadOnlyCollection(Of String)(partialPaths)
End Sub
Public Function CompareTo(obj As Object) As Integer Implements IComparable.CompareTo
Return CompareTo(DirectCast(obj, FileSystemPath))
End Function
Public Function CompareTo(other As FileSystemPath) As Integer Implements IComparable(Of FileSystemPath).CompareTo
Dim result = 0
'Compare up to as many folders as are in the shortest path.
For i = 0 To Math.Min(PartialPaths.Count, other.PartialPaths.Count) - 1
result = PartialPaths(i).CompareTo(other.PartialPaths(i))
If result <> 0 Then
'A difference has been found.
Exit For
End If
Next
If result = 0 Then
'No difference was found so put the shortest path first.
result = PartialPaths.Count.CompareTo(other.PartialPaths.Count)
End If
Return result
End Function
Public Overrides Function ToString() As String
Return FullPath
End Function
End Class
Его можно использовать, практически не внося изменений в ваш код:
Dim a As New List(Of FileSystemPath)
a.Add(New FileSystemPath("abc"))
a.Add(New FileSystemPath("abcd"))
a.Add(New FileSystemPath("abc d"))
a.Add(New FileSystemPath("abc de"))
a.Add(New FileSystemPath("abcdf"))
a.Sort()
Console.WriteLine(String.Join(Environment.NewLine, a))
Console.ReadLine()
Комментарии:
1. Во-первых, как это может быть в 10 раз медленнее, чем не делать этого вообще? Во-вторых, как насчет того, чтобы в будущем не тратить время людей и фактически информировать их, если вы сделали что-то, что работает, но не соответствует вашим требованиям к производительности? Вам не нужно говорить, что вам нужно опубликовать то, что вы уже сделали. Я почти собирался заставить вас приложить усилия, но потом подумал, что окажу вам услугу, а теперь оказывается, что вы зря потратили мое время. Я больше не повторю эту ошибку.
2. Тем не менее, часть проблемы будет заключаться в том, что первый фрагмент кода разделяет оба пути при каждом сравнении. Я на самом деле не принимал это во внимание, но второй вариант в ответе, т. е.
FileSystemPath
класс, разделяет каждый путь только один раз, поэтому он должен быть заметно быстрее.3. Спасибо, мы постараемся сообщить.