Get a distinct list of values from a one property in a List (Of T)

BrettNelson

Member
Joined
Apr 8, 2016
Messages
11
Programming Experience
Beginner
The code below, specifically Sub Button1_Click, creates a distinct list (distinctList) of values from the List(Of MainObject).

My question is - even though it produces the exact results I'm looking for, the logic seems cluttered. Anyone know of a cleaner or more direct way to create this distinct list of MainList.Prop2?
VB.NET:
Public Class Form1

    Private MainList As New List(Of MainObject)

    Public Sub New()

        InitializeComponent()
        MainList.Add(New MainObject With {.Prop1 = "1", .Prop2 = "val 1"})
        MainList.Add(New MainObject With {.Prop1 = "2", .Prop2 = "val X"})
        MainList.Add(New MainObject With {.Prop1 = "1", .Prop2 = "val 1"}) ' "val 1" is a Duplicate
        MainList.Add(New MainObject With {.Prop1 = "1", .Prop2 = "val N"})

    End Sub

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

        Dim distinctList As New List(Of OnePropObj)

        For Each itm As MainObject In MainList

            Dim findObj As New OnePropObj

            findObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)

            If findObj Is Nothing Then
                distinctList.Add(New OnePropObj With {.ValueX = itm.Prop2}) ' this line loads the distinctList
            End If

        Next
        ' when flow arrives here (distinctList) holds/stores the correct data, 3 elements

    End Sub

    Private Class OnePropObj
        Public Property ValueX As String
    End Class

    Private Class MainObject
        Public Property Prop1 As String
        Public Property Prop2 As String
    End Class

End Class
 
Last edited by a moderator:
If what you want is a list of the distinct Prop2 values then just do this:
VB.NET:
Dim distinctList = MainList.Select(Function(mo) mo.Prop2).Distinct().ToList()
There's no need for that extra type if all it will do is wrap the property values. Just use the property values themselves. In this case, distinctList will be a List(Of String).
 
By the way, don't use FirstOrDefault if you don't care about the object but only whether the object exists. If you were going to do it like you were, rather than this:
VB.NET:
findObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)

If findObj Is Nothing Then
you would do this:
VB.NET:
If Not distinctList.Any(Function(xx) xx.ValueX = itm.Prop2) Then
Also, don't create objects that you never use. What is the point of this:
VB.NET:
Dim findObj As New OnePropObj

findObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)
You declare the variable and assign a new object to it, then you immediately discard that object and assign the result of a method to the variable. Only use the New keyword if you actually want a new object. That code should have been this:
VB.NET:
Dim findObj As OnePropObj

findObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)
or, even better, this:
VB.NET:
Dim findObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)
There's no point separating the declaration and initialisation of a variable if nothing happens in between. There's also no need to specify the type of a variable if it can be inferred from the initialising expression, although you can if you want to:
VB.NET:
Dim findObj As OnePropObj = distinctList.FirstOrDefault(Function(xx) xx.ValueX = itm.Prop2)
 
Back
Top