How to Group by using LINQ in VB.NET?

Steven Young 261 Reputation points
2021-02-17T10:28:32.647+00:00

The following code can find duplicate files based on the same file size. But I want to dynamically increase more search conditions. For example, when the variable compareName = true, add the condition that compare the file name (New FileInfo(myFile).Name); when the variable compareCreationTime = true, add the condition that compare the Creation time (New FileInfo(myFile).CreationTime).
How to do it? Thank you.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim path As String = "C:\test"

    Dim files As New List(Of String)
    files.AddRange(FileIO.FileSystem.GetFiles(path, FileIO.SearchOption.SearchAllSubDirectories))

    Dim myQuery = From myFile In files
                  Group New FileInfo(myFile).FullName By myFileInfo = New FileInfo(myFile).Length
                  Into myDuplicatesGroup = Group
                  Where (myDuplicatesGroup.Count() > 1)


    Me.ListBox1.Items.Clear()

    For Each myFileGroup In myQuery
        Me.ListBox1.Items.Add("The dup. files:")
        For Each MyFile In myFileGroup.myDuplicatesGroup
            Me.ListBox1.Items.Add(MyFile)
        Next
        Me.ListBox1.Items.Add(" ")
    Next
End Sub
Developer technologies VB
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Viorel 122.6K Reputation points
    2021-02-17T12:30:10.453+00:00

    You can find several lists by each condition, then combine the results. If you want the intersection (not union), then try something like this:

    Dim files As List(Of FileInfo)
    
    files = (From p In FileIO.FileSystem.GetFiles(path, FileIO.SearchOption.SearchAllSubDirectories)
                Select New FileInfo(p)).ToList
    
    Dim results As IEnumerable(Of FileInfo) = files
    
    If compareLength Then
        Dim byLength = From fi In files
                        Group By fi.Length Into g = Group
                        Where g.Count() > 1
                        From i In g
                        Select i
        results = byLength
    End If
    
    If compareName Then
        Dim byName = From fi In files
                        Group By fi.Name Into g = Group
                        Where g.Count() > 1
                        From i In g
                        Select i
        results = results.Intersect(byName)
    End If
    
    If compareCreationTime Then
        Dim byCreationTime = From fi In files
                                Group By fi.CreationTime Into g = Group
                                Where g.Count() > 1
                                From i In g
                                Select i
        results = results.Intersect(byCreationTime)
    End If
    

    Adjust the code related to listbox. Use a single loop for results, which consists of FileInfo.


  2. Jack J Jun 25,296 Reputation points
    2021-02-19T07:12:47.943+00:00

    You can refer to the following code to use reflection to show the dup.files in the listbox by using linq.

    Public Class Form1  
      
        Dim path As String = "E:\Test"  
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load  
            ComboBox1.Items.Add("Length")  
            ComboBox1.Items.Add("Name")  
            ComboBox1.Items.Add("CreationTime")  
            files = (From p In FileIO.FileSystem.GetFiles(path, FileIO.SearchOption.SearchAllSubDirectories)  
                     Select New FileInfo(p)).ToList  
        End Sub  
        Public files As New List(Of FileInfo)  
      
        Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged  
      
            Dim dupfiles = files.GroupBy(Function(f) f.[GetType]().GetProperty(ComboBox1.Text).GetValue(f)).Where(Function(g) g.Count() > 1).[Select](Function(group) New With {  
                group.Key,  
                .Items = group.ToList()  
            }).ToList()  
            ListBox1.Items.Clear()  
            For Each i In dupfiles  
                ListBox1.Items.Add(i.Key)  
      
                For Each item In i.Items  
                    ListBox1.Items.Add(item.FullName)  
                Next  
      
                ListBox1.Items.Add("  ")  
            Next  
        End Sub  
    End Class  
    

    Note: I can not create two files with the same createtime, so I don't test the creatime condition.

    Result:
    69880-1.gif


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.