如何按文件名和数字排列文件列表?
我有一堆目录中的文件,我试图根据他们的types得到。 一旦我有了它们,我想通过文件名来命令它们(在它们中有一个数字,我想以这种方式命令它们)
我返回的文件是:
file-1.txt file-2.txt ... file-10.txt file-11.txt ... file-20.txt
但我得到他们的顺序看起来更接近这个:
file-1.txt file-10.txt file-11.txt ... file-2.txt file-20.txt
现在我正在使用Directory.GetFiles()
并尝试使用linq OrderBy
属性。 但是,我很不好,我需要做什么来sorting像上面的第一个列表的文件列表。
Directory.GetFiles()
似乎是返回一个string列表,所以我无法获得文件属性,如filename
或name
的列表。
这是我的代码目前:
documentPages = Directory.GetFiles(documentPath, "*.txt").OrderBy(Function(p) p).ToList()
有没有人有任何想法?
我假设file
和.txt
部分是可变的,只是在这里作为文件名和types可以变化的占位符。
我不经常使用正则expression式,所以这可能还需要一些工作,但这绝对是您需要去的方向:
Dim exp As String = "-([0-9]+)[.][^.]*$" documentPages = Directory.GetFiles(documentPath, "*.txt").OrderBy(Function(p) Integer.Parse(Regex.Matches(p, exp)(0).Groups(1).Value)).ToList()
再看一遍,我发现我错过了你正在过滤*.txt
文件,这可以帮助我们缩小expression式:
Dim exp As String = "-([0-9]+)[.]txt$"
包含testing数据的其他答案带来的另一个可能的改进是允许-
和数字之间的空格:
Dim exp As String = "-[ ]*([0-9]+)[.]txt$"
还有一点值得注意的是,如果有文本文件不符合该模式,则上述操作将失败。 如果需要,我们可以说明:
Dim exp As String = "-[ ]*([0-9]+)[.][^.]*$" Dim docs = Directory.GetFiles(documentPath, "*.txt") documentPages = docs.OrderBy( Function(p) Dim matches As MatchCollection = Regex.Matches(p, exp) If matches.Count = 0 OrElse matches(0).Groups.Count < 2 Then Return 0 Return Integer.Parse(matches(0).Groups(1).Value) End Function).ToList()
您也可以使用Integer.MaxValue
作为您的默认选项,具体取决于您希望那些出现在列表的开始还是结束。
这听起来像你可能正在寻找一个“NaturalSort” – 这种文件浏览器用来命令文件名包含数字。 为此,您需要一个自定义比较器:
Imports System.Runtime.InteropServices Partial Class NativeMethods <DllImport("shlwapi.dll", CharSet:=CharSet.Unicode)> Private Shared Function StrCmpLogicalW(s1 As String, s2 As String) As Int32 End Function Friend Shared Function NaturalStringCompare(str1 As String, str2 As String) As Int32 Return StrCmpLogicalW(str1, str2) End Function End Class Public Class NaturalStringComparer Implements IComparer(Of String) Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare Return NativeMethods.NaturalStringCompare(x, y) End Function End Class
用它来sorting你得到的结果:
Dim myComparer As New NaturalStringComparer ' OP post only shows the filename without path, so strip off path: ' (wont affect the result, just the display) Dim files = Directory.EnumerateFiles(path_name_here). Select(Function(s) Path.GetFileName(s)).ToList Console.WriteLine("Before: {0}", String.Join(", ", files)) ' sort the list using the Natural Comparer: files.Sort(myComparer) Console.WriteLine("After: {0}", String.Join(", ", files))
结果(单行节省空间):
之前:file-1.txt,file-10.txt,file-11.txt,file-19.txt,file-2.txt,file-20.txt,file-3.txt,file-9.txt,文件99.txt
之后:file-1.txt,file-2.txt,file-3.txt,file-9.txt,file-10.txt,file-11.txt,file-19.txt,file-20.txt,文件99.txt
其中一个优点是它不依赖于特定的模式或编码。 这是更多的目的,将处理文本中的多个数字集:
权力的游戏\ 4 – 一场乌鸦盛宴\ 1 – 序言.mp3
权力的游戏\ 4 – 一个乌鸦盛宴\ 2 – Prophet.mp3
…
权力的游戏\ 4 – 乌鸦盛宴\ 10 – Brienne II.mp3
权力的游戏\ 4 – 乌鸦盛宴\ 11 – Sansa.mp3
一个Natural String Sort
是如此方便,是我个人不介意通过创build一个扩展污染智能感知:
' List<string> version <Extension> Function ToNaturalSort(l As List(Of String)) As List(Of String) l.Sort(New NaturalStringComparer()) Return l End Function ' array version <Extension> Function ToNaturalSort(a As String()) As String() Array.Sort(a, New NaturalStringComparer()) Return a End Function
现在使用更简单:
Dim files = Directory.EnumerateFiles(your_path). Select(Function(s) Path.GetFileName(s)). ToList. ToNaturalSort() ' or without the path stripping: Dim files = Directory.EnumerateFiles(your_path).ToList.ToNaturalSort()