1

In other question (here: Pass an IO.DirectoryInfo property as a parameter to a function?) I asked about how to improve a function to pass a DirectoryInfo property as parametter, the problem is the code only works with ""toplevel"" properties like "Name", "Root", "Drive", etc...

But I would need to use the function like this:

Dim Folders As List(Of IO.DirectoryInfo) = blah bla blah...

For Each folderinfo In Bubble_Sort_List_DirectoryInfo(Folders, Function() New IO.DirectoryInfo("").Name)
    MsgBox(folderinfo.Name)
Next

But I need to use the function like this else:

For Each folderinfo In Bubble_Sort_List_DirectoryInfo(Folders, Function() New IO.DirectoryInfo("").Parent.Name.Length)
    MsgBox(folderinfo.Name)
Next

What is necessary to add/modify in this function to manage the usage of DirectoryInfo properties like "Name.Length" or "Parent.Name.Length"?

Private Shared Function Bubble_Sort_List_DirectoryInfo(list As List(Of IO.DirectoryInfo), _
                                                     exp As Expression(Of Func(Of Object))) _
                                                     As List(Of IO.DirectoryInfo)

    Dim member As MemberExpression = _
        If(TypeOf exp.Body Is UnaryExpression, _
           DirectCast(DirectCast(exp.Body, UnaryExpression).Operand, MemberExpression), _
           DirectCast(exp.Body, MemberExpression))

    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( _
                               list.Select(Function(folder) DirectCast(DirectCast(member.Member, PropertyInfo) _
                                                            .GetValue(folder, Nothing), Object).ToString.Length).Max(), _
                                                            If(Char.IsDigit(m.Value(0)), " "c, Char.MaxValue))) _
    }).OrderBy(Function(x) x.SortStr).Select(Function(x) x.OrgStr).ToList

End Function

UPDATE:

This are just some explanations and examples.

Inside a directory of my drive I have some folders with folder-names like these:

80's
90's
2000-2006
2007
2008

In my application I get the folders using the "IO.Directory.GetDirectories" method and I store them into a list of DirectoryInfo()

This is the input list:

Dim Folders As List(Of IO.DirectoryInfo) = _
    IO.Directory.GetDirectories("E:\Música\Canciones", "*", IO.SearchOption.TopDirectoryOnly) _
    .Select(Function(p) New IO.DirectoryInfo(p)).ToList()

...But the "IO" method causes the list contents to be sorted as string sort like this:

2000-2006
2007
2008
80's
90's

My desired output is this:

80's
90's
2000-2006
2007
2008

So after creating the List using the "IO" method I'll need to sort the list contents to get my desired output AND THAT'S EXACTLY WHAT I GET USING THE FUNCTION ABOVE calling the function using the property "Name" as parametter to bubble sort the folders by their Name property, so I get my desired output.

well the problem is I need to use other properties like "Name.Length" and "Parent.Name.Length", but the function only allows the usage of a """TopLevel""" property like "Name", "Parent", etc but not variable properties.

Community
  • 1
  • 1
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • I haven't seen part 1 of this, but why not pass a lambda expression instead of a string? So you would have some function(x) x.parent.name.length instead of "Parent.Name.Length", and then pass it via addressof or perhaps as a variable (because of simplicity). – Victor Zakharov Sep 29 '13 at 21:15
  • @Neolisk thanks for comment, one person shown me a solution using lambda but has the same problem, I've updated my question with a link to the first part of the question. I preffer the usage of strings because in this case the lambda directory path could be empty ( ex: function() new directoryinfo("").Name ) but I want to use this function in a generic way so with other kind of objects the lambda expression would force me to instance an object when just I can't, I hope you can understandme, or maybe I'm wrong IDK much about lambda usage but anyways using string or lambda I can't resolve this – ElektroStudios Sep 29 '13 at 21:31
  • 1
    You don't need to instantiate an object. You can make a lambda on a not yet existing object. Think of it as a pure function. Pure functions don't need anything to exist, they define workflow. Something goes in, something else goes out, nothing is stored. If you want generic approach, you can do lambda on type Object. No runtime checks, same as strings pretty much, but you keep the "nice" lambda syntax. – Victor Zakharov Sep 29 '13 at 22:17
  • @Neolisk thanks for the explanation then I can't use lambdas with any risk :). – ElektroStudios Sep 30 '13 at 11:01
  • I've updated the code using the lambda version, please help me! – ElektroStudios Sep 30 '13 at 13:54
  • Forget about methodology, what are trying to do? Please provide sample input and output. Your code looks too complicated. – Victor Zakharov Sep 30 '13 at 14:02
  • @Neolisk I've updated the question adding information, thanks for comment. – ElektroStudios Sep 30 '13 at 14:14
  • have you tried not sorting them ? – Sebastien H. Sep 30 '13 at 14:26
  • Great, thanks for the update. Now can you explain in words what is the rationale behind your way of sorting. I know it kind of looks like years, but how exactly in English words did you plan on sorting this out? I am asking because Length does not help you much, it would result in this order: 80's, 90's, 2007, 2008, 2000-2006 (or similar). – Victor Zakharov Sep 30 '13 at 15:32
  • You're trying to basically do smart name sorting... – It'sNotALie. Sep 30 '13 at 21:09

1 Answers1

1

Make a class that implements IComparer:

Public Class MyDirectoryInfoComparer
    Implements IComparer(Of IO.DirectoryInfo)

    Public Function Compare(x As IO.DirectoryInfo, y As IO.DirectoryInfo) As Integer _
        Implements IComparer(Of IO.DirectoryInfo).Compare

        ' x comes before y
        Return -1 ' or any number less than 0

        ' x is the same as y
        Return 0

        ' x comes after y
        Return 1 ' or any number greater than 0
End Function

Create your list:

Dim Folders As List(Of IO.DirectoryInfo) = _
    IO.Directory.GetDirectories("E:\Música\Canciones", "*", IO.SearchOption.TopDirectoryOnly) _
    .Select(Function(p) New IO.DirectoryInfo(p)).ToList()

Then use your comparer class to sort it:

Folders.Sort(New MyDirectoryInfoComparer)