views:

65

answers:

2

I have a hashtable in VB.NET and I need to get the string value of a key from it's value. For example, if I do:

hashtable.add("string1","string2")

How would I get the value "string1" if I had "string2"?

+1  A: 

You can't (at least not without simply looping through every value). Consider the fact that multiple keys can map to the same value:

hashtable.Add("string1", "string2")
hashtable.Add("string3", "string2")

Now given "string2" what would you expect to be returned?

If you really need to do a "reverse" lookup, then the simplest solution is to probably have two hashtable, one for the "forward" lookup and one for the "reverse" lookup.

Dean Harding
So it's only one way then? Is there a structure in VB.NET that can do this? I'm trying to minimize code as the hashtable will probably get quite big.
Steven
@Steven: Not that I'm aware of. It shouldn't be a big deal to have two since you can just build a wrapper class to manage it and the collections only ever store references anyway, so the amount of extra data will be minimal.
Dean Harding
@Dean Thanks for the help! I guess I'll use two. I appreciate it.
Steven
A: 

As Dean / codeka says you can't strictly do this.

However you can do something like this as the Keys and Values of a Hashtable are in the same (unspecified) order:

Hashtable ht = new Hashtable();
ht.Add("string1", "str2");
ht.Add("string2", "str2");

List<string> keys = new List<string>(ht.Keys.OfType<string>());

string key = ht.Values.OfType<string>()
  .Select((htI, i) => new { Key = keys[i], Value = htI })
  .Where(htKVP => htKVP.Value == "str2")
  .Select(htKVP => htKVP.Key)
  .FirstOrDefault();

However, you would be better using a Dictionary<string, string> just because it is generically typed and lets you get to Linq easier.

Converted for VB.NET that is:

Dim ht as new Hashtable()
ht.Add("string1", "str2")
ht.Add("string2", "str2")

Dim keys as new List(Of String)(ht.Keys.OfType(Of String)())

Dim key as String = ht.Values.OfType(Of String)() _
  .Select(Function(htI, i) New With { .Key = keys(i), .Value = htI }) _
  .Where(Function(htKVP) htKVP.Value = "str2") _
  .Select(Function(htKVP) htKVP.Key) _
  .FirstOrDefault()

But again I'd start with:

Dim dt as New Dictionary(Of String, String)

You could add this as an extension method like so:

Imports System.Runtime.CompilerServices

Module StringExtensions

    <Extension()> 
    Public Function FirstKeyForValue(ByVal Hashtable as ht, ByVal value As String) As String
      return ht.Values.OfType(Of String)() _
      .Select(Function(htI, i) New With { .Key = keys(i), .Value = htI }) _
      .Where(Function(htKVP) htKVP.Value = "str2") _
      .Select(Function(htKVP) htKVP.Key) _
      .FirstOrDefault()        
    End Function

End Module
Graphain