0

I have a List of DirectoryInfo wich contains folder names like these:

80's
90's
2000
2001

The problem is that the "IO.Directory.GetDirectories" function returns the generic Microsoft Sort so my list is sorted as this:

2000
2001
80's
90's

I know the algorithm to Bubble sort (always I see the usage of a FOR and to generate other temporal objects, I don't like any Bubble sort method I've seen) and I hope if a Bubble Sort can be simplified using LINQ or other improved methods but not a For neither creating extra objects in memory.

How I can Bubble Sort the List(Of DirectoryInfo) by their Directory.Name property ? (obviouslly I want to preserve the DirectoryInfo objects, not to return a couple of sorted Strings), also is possibly to bubble sort it without reallocating the list using LINQ extensions?

UPDATE:

If someone need the information this is the function that I'm using to get the DirectoryInfo list:

' Get Folders
Private Function Get_Folders(ByVal directory As String, ByVal recursive As Boolean) As List(Of IO.DirectoryInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Return IO.Directory.GetDirectories(directory, "*", searchOpt).Select(Function(p) New IO.DirectoryInfo(p)).ToList
End Function

UPDATE 2

Following the suggestions on question comments I'm trying to simplify all the code in just few lines using a regex and LINQ extensions treating the folder names as integers to sort them, the problem is it fails because I have some folders who can't be converted to numbers, this is a example folder names:

80's
90's
2000-2006
2007
2008
Classic
B.S.O
Maquetas

My question is If I can exlude the Non-Digits folders when sorting and then append that excluded folders to the sorted "integer" folder names, I ask this just to don't get all the folders two times to generate two different lists to join them.

Also notice the folder name "2000-2006", if I convert the name to integer I wouldn't get the expected result when sorting.

So just how I could Bubble sort the list folder name content treating them as what are?, strings, not numbers.

Public Class Form1

Dim regex As New System.Text.RegularExpressions.Regex("\D")

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Shown

    For Each folder In Get_Folders("E:\Música\Canciones", False) _
                       .OrderBy(Function(x) Convert.ToInt32(regex.Replace(x.Name, "")))

        MsgBox(folder.Name)
        ' Exception here, because a folder named "B.S.O" and other named as "Classic",
        ' obviouslly they can't be converted to Integer :(

    Next

End Sub

' Get Folders
Private Function Get_Folders(ByVal directory As String, ByVal recursive As Boolean) As List(Of IO.DirectoryInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Return IO.Directory.GetDirectories(directory, "*", searchOpt).Select(Function(p) New IO.DirectoryInfo(p)).ToList
End Function

End Class
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • http://stackoverflow.com/a/11052176/932418 – L.B Sep 29 '13 at 14:20
  • @L.B Thankyou, that solution is a little hardcoded I'm trying to delete all the unnecesary things like the splits and the substrings but maybe I can need help to retouch that solution 'cause I don't know if the result will work with my list. – ElektroStudios Sep 29 '13 at 14:26
  • Elektro Hacker, I tested that solution, and it works for your case (I am talking about my answer not the accpted one :) ) . – L.B Sep 29 '13 at 14:29
  • Oh really sorry I didn't noticed you answered there, I have nothing to do with your C# answer, I can't translate it to VBNET even with online translators. – ElektroStudios Sep 29 '13 at 14:35
  • 1
    I am curious what sort criteria you think will give you the result you want. What you called the 'generic MS sort' IS alphabetical: '2' comes before '8' comes before '9' in ASCII. I have the same quibble with the exact folder structure for music files and just changed '70s', '80s' etc to '1970s', '1980s' etc. – Ňɏssa Pøngjǣrdenlarp Sep 29 '13 at 14:50
  • @Plutonix Ok I understand I need to treat the folder names as digits, but I have a problem with that, please see my update if you can help me. – ElektroStudios Sep 29 '13 at 15:38

2 Answers2

1

I translated the code in referenced question using Telerik's online converter. It works for your case too.

Public Shared Function CustomSort(list As IEnumerable(Of String)) As IEnumerable(Of String)
    Dim maxLen As Integer = list.[Select](Function(s) s.Length).Max()

    Return list.[Select](Function(s) New With { _
        Key .OrgStr = s, _
        Key .SortStr = System.Text.RegularExpressions.Regex.Replace(s, "(\d+)|(\D+)", Function(m) m.Value.PadLeft(maxLen, If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
    }).OrderBy(Function(x) x.SortStr).[Select](Function(x) x.OrgStr)
End Function
Community
  • 1
  • 1
L.B
  • 114,136
  • 19
  • 178
  • 224
  • I've tried to use it passing as parametter a list of io.directoryinfo doing some modifications inside the function but just impossible for me, could you help me to edit the code? EDIT: Oh finally I got it adding ".Tolist" when returning the data, thanks so much i will post the modification – ElektroStudios Sep 29 '13 at 15:48
1

Little modification of @L.B solution, I hope this helps someone else:

    Public Shared Function CustomSort(list As List(Of IO.DirectoryInfo)) As List(Of IO.DirectoryInfo)

        Dim maxLen As Integer = list.[Select](Function(s) s.Name.Length).Max()

        Return list.[Select](Function(s) New With { _
            Key .OrgStr = s, _
            Key .SortStr = System.Text.RegularExpressions.Regex.Replace(s.Name, "(\d+)|(\D+)", Function(m) m.Value.PadLeft(maxLen, If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
        }).OrderBy(Function(x) x.SortStr).[Select](Function(x) x.OrgStr).ToList
    End Function
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417