yu_ominae
yu_ominae

Reputation: 2935

vb.NET Select distinct... how to use it?

Coming from a C# background I am a bit miffed by my inability to get this simple linq query working:

Dim data As List(Of Dictionary(Of String, Object))
Dim dbm As AccessDBManager = GlobalObjectManager.DBManagers("SecondaryAccessDBManager")

data = dbm.Select("*", "T町丁目位置_各務原")

Dim towns As IEnumerable(Of String()) 
        towns = data.Select(Function(d) New String() {d("町名_Trim").ToString(), d("ふりがな").ToString()})
        towns = towns.Where(Function(s) s(0).StartsWith(searchTerms) Or s(1).StartsWith(searchTerms)).Distinct()

Call UpdateTownsListView(towns.ToList())

I pasted together the relevant bits, so hopefully there is no error here...

data is loaded from an access database and is a list with the data from each row stored as a dictionary.

In this case element from data has a field containing the name of a Japanese town and its reading and some other stuff like the row ID etc.

I have a form with a textbox. When the user types something in, I would like to retrieve from data the town names corresponding to the search terms without duplicates.

Right now the results contain loads of duplicates> How can I get this sorted to only get distinct results?

I read from some other posts that a key might be needed, but how can I declare this with extension methods?

Upvotes: 2

Views: 1721

Answers (1)

sloth
sloth

Reputation: 101072

Distinct uses the default equality comparer to compare values.

Your collection contains arrays of strings, so Distinct won't work the way you expected since two different arrays never equals each other (since ReferenceEquals would be used in the end).


A solution is to use the Distinct overload which takes an IEqualityComparer.

Class TwoStringArrayEqualityComparer 
    Implements IEqualityComparer(Of String())

    Public Function Equals(s1 As String(), s2 As String()) As Boolean Implements IEqualityComparer(Of String()).Equals
        ' Note that checking for Nothing is missing
        Return s1(0).Equals(s2(0)) AndAlso s1(1).Equals(s2(1))
    End Function

    Public Function GetHashCode(s As String()) As Integer Implements IEqualityComparer(Of String()).GetHashCode
        Return (s(0) + s(1)).GetHashCode() ' probably not perfect :-)
    End Function

End Class

...

towns = towns.Where(...).Distinct(new TwoStringArrayEqualityComparer())

Upvotes: 1

Related Questions