我有以下文件列表
10_2017
123_2018
500_2017
20_2019
100_2017
25_2017
32_2018
我想被排序为
10_2017
25_2017
100_2017
500_2017
32_2018
123_2018
20_2019
如果我将年份分开阅读,则可以按Array.sort(f1,new FileInfoSort)
对数组进行排序,但我需要将其放在一个排序的数组或列表中
我在这里尝试了多个线程,包括此method。使用f1.Sort(Function(x, y) x.Name.CompareTo(y.Name))
和Array.Sort(f1.toArray, New FileInfoSort)
均未成功
我什至试图按年份将文件分成文件夹,然后分别将它们读入列表,然后将它们组合在一起,这似乎也不起作用
使用代码
Dim d1 As New DirectoryInfo(AppFolder)
Dim f1 As List(Of FileInfo) = d1.GetFiles("*.LBK", SearchOption.TopDirectoryOnly).ToList
'f1.Sort(Function(x, y) x.Name.CompareTo(y.Name))
f1.SortNatural(Function(x) x.Name)
按年份将文件分成文件夹,然后阅读并合并
Dim d1 As New DirectoryInfo(AppFolder.User.data)
Dim d2 As List(Of DirectoryInfo) = New List(Of DirectoryInfo)
'data folders have names like "d_2019"
For Each d As DirectoryInfo In d1.GetDirectories
If d.Name.ToString.Substring(0, 1) = "d" Then d2.Add(d)
Next
Dim f1 As List(Of FileInfo) = New List(Of FileInfo)
For Each Dir As DirectoryInfo In d2
f1.AddRange(Dir.GetFiles("*.LBK", SearchOption.TopDirectoryOnly))
'trying to sort
'f1.Sort(Function(x, y) x.Name.CompareTo(y.Name))
f1.SortNatural(Function(x) x.Name)
Next
Module ListExt
<DllImport("shlwapi.dll", CharSet:=CharSet.Unicode)>
Private Function StrCmpLogicalW(ByVal lhs As String, ByVal rhs As String) As Integer
End Function
<Extension()>
Sub SortNatural(Of T)(ByVal self As List(Of T), ByVal stringSelector As Func(Of T, String))
self.Sort(Function(lhs, rhs) StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs)))
End Sub
<Extension()>
Sub SortNatural(ByVal self As List(Of String))
self.Sort(AddressOf StrCmpLogicalW)
End Sub
End Module
到目前为止,我已经使用过的任何方法
10_2017
20_2019
25_2017
32_2018
100_2017
123_2018
500_2017
我什至不知道该如何处理。如果这样的列表/数组不可行,那么我将如何构造我的文件,以便我可以按照上面我喜欢的顺序读取文件的想法也将受到欢迎!
答案 0 :(得分:1)
您将必须编写代码来解析名称的各个部分,并将其视为数字。您使用的任何内置比较器都将字符串视为字符串,以1开头的任何内容都以2开头的任何内容都在字符串之前,即使值是'100'和'2'。甚至所谓的“自然”排序也仅足以检查第一部分。
您还需要从名称中去除LBK
扩展名。
Dim splitChars() As Char = {"_"c}
Dim d1 As New DirectoryInfo(AppFolder)
Dim f1 As List(Of FileInfo) =
d1.EnumerateFiles("*.LBK", SearchOption.TopDirectoryOnly).
OrderBy(Function(fi)
Dim parts = fi.Name.Replace(".LBK", "").Split(splitChars)
Return (Integer.Parse(parts(1)) * 1000) + Integer.Parse(parts(0))
End Function).
ToList()
为了娱乐,这是一个正则表达式版本:
Dim exp As New Regex("(\d{1,3})_(\d{4})");
Dim d1 As New DirectoryInfo(AppFolder)
Dim f1 As List(Of FileInfo) =
d1.EnumerateFiles("*.LBK", SearchOption.TopDirectoryOnly).
OrderBy(Function(fi)
Dim parts = exp.Matches(fi.Name)(0).Groups
Return (Integer.Parse(parts(2).Value) * 1000) + Integer.Parse(parts(1).Value)
End Function).
ToList()
在这里看到它的工作
我还想从问题中的一个样本中对此行发表评论:
If d.Name.ToString.Substring(0, 1) = "d" Then d2.Add(d)
它特别引人注意。这里有 ton 多余的工作正在进行,
ToString()
Substring()
您真的想要这个:
If d.Name(0) = "d"c Then d2.Add(d)
这是一个很多的代码,它的性能会好得多,值得您花时间研究一下并理解原因。