Search code examples
vb.netdictionarycontains

ContainsValue with Dictionary(Of String, Items)


How to know if a dictionary with multiple values contains specific value?

'Create dictionary
Dim testDictionary As New Dictionary(Of String, Items)

'Code to fill dictionary
'.......................
'.......................
'.......................

'Test if a specific value is contained in dictionary
Dim testValue as String = "TEST"
testDictionary.ContainsValue(testValue) 'This doesn't work

Public Class Items
    Public Property Property1 As String
    Public Property Property2 As String
    Public Sub New()
    End Sub
End Class

Solution

  • If you can define how to determine whether the dictionary contains that string, pass that logic into Enumerable.Any

    Dim testValue As String = "TEST"
    
    Dim contains = testDictionary.Any(Function(kvp) kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue)
    If contains Then
        Dim containsEntries = testDictionary.Where(Function(kvp) kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue)
    End If
    

    Since you reuse it for Any and Where, you can declare the predicate once

    Dim predicate =
        Function(kvp As KeyValuePair(Of String, Items))
            Return kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue
        End Function
    Dim contains = testDictionary.Any(predicate)
    If contains Then
        Dim containsEntries = testDictionary.Where(predicate)
    End If
    

    This is hard-coded to just these properties Property1 and Property2.

    (you really don't need the Any if you want the entities; I just figured the Any answered your question "How to know if..." with a boolean)

    If you want to check all public instance string properties, you can use reflection

    Dim predicate =
        Function(kvp As KeyValuePair(Of String, Items))
            Return GetType(Items).
                GetProperties(Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance).
                Where(Function(pi) pi.PropertyType Is GetType(String)).
                Aggregate(False, Function(pi1, pi2) pi1 Or (pi2.GetValue(kvp.Value) = testValue))
        End Function
    Dim containsWith = testDictionary.Any(predicate)
    If containsWith Then
        Dim containsEntries = testDictionary.Where(predicate)
    End If