Graeme_Grant
Требование: двойная буква оборотов-от a до z-затем повторите с aa, ab, ac...и т. д. С rev aa перед z. длина перед Альфа, затем убывающая на альфа.
Таким образом, для пользовательской сортировки версии ревизии Интерфейс IComparer<t>
[^] лучше всего подходит для этой задачи. Вот компаратор, который будет сортировать по длине, а затем по буквам альфа-версии:
Class RevisionComparer
Implements IComparer(Of String)
Private Function IComparer_Compare(x As String, y As String) As Integer _
Implements IComparer(Of String).Compare
' same values
If x = y Then Return 0
' different lengths
If x.Length > y.Length Then Return 1
If x.Length < y.Length Then Return -1
' the same length, more work required
If x.Length = y.Length Then
For i As Integer = 0 To x.Length - 1
' check by position
If x(i) > y(i) Then Return 1
If x(i) < y(i) Then Return -1
Next
End If
' must be identical, so no change
Return 0
End Function
End Class
Прежде чем мы сможем что-либо сделать, нам нужно создать и протестировать
RevisionComparer
класс:
Module Module1
Sub Main()
Dim testRevisions = New List(Of String)() From {
"c",
"aa",
"az",
"ba",
"bz",
"aaa",
"bca",
"cba",
"aza",
"azz"
}
Dim sortedRevisions = testRevisions.OrderByDescending(Function(x) x, New RevisionComparer())
For Each item In sortedRevisions
Console.WriteLine(item)
Next
Console.WriteLine("-- DONE --")
Console.ReadKey()
End Sub
End Module
Который выводит:
cba
bca
azz
aza
aaa
bz
ba
az
aa
c
-- DONE --
Итак, теперь мы готовы к главному событию.
Требования таковы:
1. файлы называются в этом формате-drawing number_revision_page_date
.... пример 0092933_C_1-2_061217. pdf
2. двойная буква оборотов-от А до Я-затем повторите с aa,ab, ac...и т. д.
3. Дата до пересмотра??? (предполагается, что не уточняется)
Вот решение, основанное на вышеуказанных 3-х выявленных требованиях. (Примечание: легко изменить)
Во-первых, нам нужно разбить имя файла на его части:
Class FileType
Public Property ID As String
Public Property Name As String
Public Property Revision As String
Public Property [Date] As String
Public Property Pages As String
End Class
Используя
RevisionComparer
выше мы теперь можем сортировать имена файлов:
Module Module1
Sub Main()
' test data
Dim files = New List(Of String)() From {
"0092933_C_1-2_061117.pdf",
"0092933_Z_1-2_120617.pdf",
"0092933_AZ_1-2_120617.pdf",
"1092933_AB_1-2_061117.pdf",
"1092933_Z_1-2_120617.pdf",
"1092933_CZ_1-2_120617.pdf"
}
Dim data As New List(Of FileType)()
For Each file In files
' break up the filename
Dim parts = IO.Path.GetFileNameWithoutExtension(file).Split(New Char() {"_"c}, StringSplitOptions.RemoveEmptyEntries)
' valid number of parts
If parts.Length = 4 Then
Dim fileDate = Nothing
DateTime.TryParse(parts(2), fileDate)
data.Add(New FileType() With {
.ID = parts(0),
.Revision = parts(1),
.[Date] = parts(2),
.Pages = parts(3),
.Name = file
})
End If
Next
' sort the files by: date desc, then revision desc...
Dim sorted = data.OrderByDescending(Function(x) x.[Date]) _
.ThenByDescending(Function(x) x.Revision, New RevisionComparer()) _
.GroupBy(Function(x) x.ID) _
.Select(Function(x) x.First())
' report the results
For Each item In sorted
Console.WriteLine(item.Name)
Next
Console.WriteLine("-- DONE --")
Console.ReadKey()
End Sub
End Module
Который выводит:
1092933_CZ_1-2_120617.pdf
0092933_AZ_1-2_120617.pdf
-- DONE --
ОБНОВЛЕНИЕ: Вы просите "решение только для Linq", и ответ-да, вы можете избежать дополнительных классов и сделать это одним очень длинным запросом Linq, но тогда все сводится к удобочитаемости и ремонтопригодности. Вышеприведенное решение ставит галочки в обоих этих ящиках.
Однако вы запросили однострочный запрос Linq, так что вот он, используя вышеприведенный компаратор из-за требования пользовательской сортировки. Все используемые части находятся в приведенном выше более красноречивом решении:
Dim sortedV2 = files.Select(Function(x) IO.Path.GetFileNameWithoutExtension(x).Split(New Char() {"_"c}, StringSplitOptions.RemoveEmptyEntries)) _
.OrderByDescending(Function(x) x(2)) _
.ThenByDescending(Function(x) x(1), New RevisionComparer()) _
.GroupBy(Function(x) x(0)) _
.Select(Function(x) x.First()) _
.Select(Function(x) String.Join("_", x) + ".pdf")
' report the results
For Each item In sortedV2
Console.WriteLine(item)
Next
Примечание: проблема с этим однострочным решением Linq заключается в том, что если у вас есть неправильно названный файл, оператор Linq вызовет исключение, однако вышеупомянутое "оригинальное" решение этого не сделает.