How to order list of files by file name with number?

后端 未结 2 528
春和景丽
春和景丽 2020-11-28 17:14

I have a bunch of files in a directory that I am trying to get based off their type. Once I have them I would like to order them by file name (there is a number in them and

2条回答
  •  醉梦人生
    2020-11-28 17:21

    It sounds like you might be looking for a "NaturalSort" - the kind of display File Explorer uses to order filenames containing numerals. For this you need a custom comparer:

    Imports System.Runtime.InteropServices
    
    Partial Class NativeMethods
        
        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
    

    Use it to sort the results you get:

    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))
    

    Results (one-lined to save space):

    Before: file-1.txt, file-10.txt, file-11.txt, file-19.txt, file-2.txt, file-20.txt, file-3.txt, file-9.txt, file-99.txt
    After: file-1.txt, file-2.txt, file-3.txt, file-9.txt, file-10.txt, file-11.txt, file-19.txt, file-20.txt, file-99.txt

    One of the advantages of this is that it doesnt rely on a specific pattern or coding. It is more all-purpose and will handle more than one set of numbers in the text:

    Game of Thrones\4 - A Feast For Crows\1 - Prologue.mp3
    Game of Thrones\4 - A Feast For Crows\2 - The Prophet.mp3
    ...
    Game of Thrones\4 - A Feast For Crows\10 - Brienne II.mp3
    Game of Thrones\4 - A Feast For Crows\11 - Sansa.mp3


    A Natural String Sort is so handy, is is something I personally dont mind polluting Intellisense with by creating an extension:

    ' List version
    
    Function ToNaturalSort(l As List(Of String)) As List(Of String)
        l.Sort(New NaturalStringComparer())
        Return l
    End Function
    
    ' array version
    
    Function ToNaturalSort(a As String()) As String()
        Array.Sort(a, New NaturalStringComparer())
        Return a
    End Function
    

    Usage now is even easier:

    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()
    

提交回复
热议问题