Eric Snyder
Eric Snyder

Reputation: 1924

Dictionary entries with two keys - VB.net

What would the .net experts recommend? I have a piece of data that I need to access using two different keys. Let's say the data looks like this:

key1
key2
data

I need to add, find data by either key and delete the data using either key thousands of times and want to make it very quick.

I really like the clarity that LINQ adds to the code but...I have compared LINQ to dictionaries in loop retrieval situations. I don't like LINQ because it looks like it takes far more time to get any single piece of data. I like dictionaries because they are so fast with retrieval.

I was thinking of writing a custom class that uses two dictionaries:

key1
data

and

key2
data

any time I add a data item to the instance of the class the class would need to add the data to two different backing dictionaries. Every time I remove a data item I would need to remove them from both backing dictionaries.

Is this the best way to handle this issue or is there some fast "dictionary like" data structure in .net that allows me to have two keys for the same data?

Upvotes: 3

Views: 5579

Answers (4)

JFPicard
JFPicard

Reputation: 5168

A little late, but how about concatenate the key1 with the key 2 like:

key1key2
data

With that, you can always get the data without all the fuss. You can add then like this:

 Public DictVal As New Dictionary(Of String, String)

  DictVal.Add(key1 & key2, value)

Upvotes: 0

WeSe
WeSe

Reputation: 1

I'm really surprised that I got a solution here (because I am a noob to this kind of programming).

So there is two things to consider: You need to know which key you are using for the search and as well add and delete entries aside of each other. I guess you could do overcome these things with a shared sub for adding and deleting entries or maybe even with a class (don't know much about them).

Maybe someone can improve on that.

I did, see section below ;-]

    Dim myDict As New Dictionary(Of String, Double)
    Dim myKeyDict As New Dictionary(Of String, String)
    myDict.Add("key1", 5.5)
    myKeyDict.Add("key2", "key1")

    ' Access Dictionary with key1
    myDict("key1") = 7.7
    Debug.Print(CStr(myDict("key1")))

    ' Acces Dictionary with key2
    Dim thisKey1 As String = myKeyDict("key2")  ' retrieve key1 with the help of key2
    Debug.Print(CStr(myDict(thisKey1)))         ' Acces the actuall dictionary with the retrieved key 1

So I created a class for a dictionary with key1 as string, key2 as string and val as double with basic in and output operations:

Public Class MultiKeyDictonaryDbl
    Public DictVal As New Dictionary(Of String, Double)         ' key1=Variablenname, val=Wert
    Public DictKey1 As New Dictionary(Of String, String)        ' key1=In/Output-Variablenname (Textdatei), key2=Variablenname
    Public DictKey2 As New Dictionary(Of String, String)        ' key2=In/Output-Variablenname (Textdatei), key1=Variablenname
    Public length As Integer
    Public Sub Add(key1 As String, key2 As String, val As Double)
        DictVal.Add(key1, val)
        DictKey1.Add(key1, key2)
        DictKey2.Add(key2, key1)
    End Sub
    Public Sub Remove(key As String, id As Integer)
        Dim key1 As String = Nothing
        Dim key2 As String = Nothing
        Dim chk As Boolean
        If id = 1 Then
            key1 = key
            chk = DictKey1.TryGetValue(key1, key2)
        ElseIf id = 2 Then
            key2 = key
            chk = DictKey2.TryGetValue(key2, key1)
        End If
        If chk = True Then
            DictVal.Remove(key1)
            DictKey1.Remove(key1)
            DictKey2.Remove(key2)
        End If
    End Sub
    Public Function getValue(key As String, id As Integer) As Double
        Dim key1 As String = Nothing
        Dim key2 As String = Nothing
        Dim chk As Boolean
        If id = 1 Then
            key1 = key : chk = True
        ElseIf id = 2 Then
            key2 = key
            chk = DictKey2.TryGetValue(key2, key1)
        End If
        If chk = True Then
            chk = DictVal.TryGetValue(key1, getValue)
        End If
        If chk = False Then getValue = Double.PositiveInfinity
    End Function
    Public Function getList() As String(,)
        Dim val As Double
        Dim key1 As String = Nothing
        Dim key2 As String = Nothing
        Dim i As Integer = -1
        ' getLength in one line of code
        length = -1 : Dim l1 As Integer = DictVal.Count : Dim l2 As Integer = DictKey1.Count : Dim l3 As Integer = DictKey2.Count : If l1 = l2 And l2 = l3 Then length = l1
        If length < 1 Then Exit Function
        Dim List(length - 1, 2) As String
        For Each ele In DictKey2
            i += 1
            key2 = ele.Key : key1 = DictKey2(key2) : val = DictVal(key1)
            List(i, 0) = key1 : List(i, 1) = key2 : List(i, 2) = CStr(val)
        Next
        getList = List
    End Function
    Public Function getLength() As Integer
        getLength = -1
        Dim l1 As Integer = DictVal.Count
        Dim l2 As Integer = DictKey1.Count
        Dim l3 As Integer = DictKey2.Count
        If l1 = l2 And l2 = l3 Then getLength = l1
        length = getLength
    End Function
End Class

Sub testDictionaryVariablenVerarbeitung()
    ' some tests
    Dim testit As New MultiKeyDictonaryDbl
    testit.Add("Variablenname", "In/Output-Variablenname", 55.7)
    testit.Add("Variablenname2", "In/Output-Variablenname2", 90.7)
    Debug.Print(CStr(testit.getLength()))
    testit.Add("Blub", "dabdi", 916)
    testit.Remove("Variablenname", 1)

    Dim liste(,) As String = testit.getList
    Debug.Print(CStr(testit.getValue("Variablenname2", 1)))
    Debug.Print(CStr(testit.getValue("dabdi", 2)))
    Debug.Print(CStr(testit.getValue("dabdi", 1)))

End Sub

Upvotes: 0

suff trek
suff trek

Reputation: 39777

You can define a composite key e.g.

Structure CKey
    Public Key1 As String
    Public Key2 As String
End Structure

And Dictionary that uses that key

Dim myDict As New Dictionary(Of CKey, String)

myDict.Add(New CKey() With {.Key1 = "key01", .Key2 = "key02"}, "Data0102")
myDict.Add(New CKey() With {.Key1 = "key11", .Key2 = "key12"}, "Data0103")
myDict.Add(New CKey() With {.Key1 = "key01", .Key2 = "key22"}, "Data0104")
myDict.Add(New CKey() With {.Key1 = "key11", .Key2 = "key22"}, "Data0105")

Then you can run a simple LINQ query like:

Dim result = From el In myDict Where el.Key.Key1 = "key01" Select el

If you don't like LINQ you can still loop thru the dictionary in your own methods, checking the keys yourself.

Upvotes: 0

Reed Copsey
Reed Copsey

Reputation: 564413

Is this the best way to handle this issue or is there some fast "dictionary like" data structure in .net that allows me to have two keys for the same data?

There is no built in data structure that provides two keys, where either key can be used.

Given that you want to lookup by either key (and not both at once), using a custom class which encapsulates two Dictionary(Of TKey, Of TValue) makes sense, provided that the overhead of storing both dictionaries is not objectionable.

Upvotes: 1

Related Questions