Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Bidirectional Hashtable

0.00/5 (No votes)
31 Aug 2003 1  
Demonstrates an easy-to-use bidirectional Hashtable to facilitate reverse lookups.

Introduction

Sometimes you have data with a 1:1 relationship that you put into a Hashtable, use for awhile, and later realize you need to look up the keys from the values in the table. This article introduces a class to solve this problem.

Background

The brain-dead solution is to have two hashtables (one forward, one backward), and add everything into both. This is a bit of a pain; why not have a class to manage this, and save ourselves from redundant typing? After having this problem a couple of times, I resolved to not type things in twice, anymore. Enter BidirHashtable, a bidirectional Hashtable.

Using the code

BidirHashtable is easy to create, though it doesn't support the rich set of constructors that Hashtable does.

BidirHashtable bh = new BidirHashtable();

The interface to BidirHashtable is essentially identical to that of Hashtable, except that internally it is managing two Hashtable objects. For example:

bh[1] = 101;
bh[2] = 102;

Caveat: You'll want to make sure only to use a 1:1 relationship. While 1:n relationships are impossible to establish with Hashtable or BidirHashtable, n:1 relationships are possible with Hashtable. BidirHashtable, however, is not designed with n:1 in mind, because for BidirHashtable it means a 1:n relationship for the reverse table--patently impossible. So be warned--and don't try it.

bh[1] = 101;
bh[2] = 101;  // don't try this

Checking whether elements are in the table is easy:

System.Diagnostics.Debug.Assert( bh.Contains(1) );
System.Diagnostics.Debug.Assert( bh.ContainsValue(101) );

Note the ContainsValue() function. This is in Hashtable, but in BidirHashtable, it is actually faster, as it does its lookup using the reverse table.

Forward lookups are also as in Hashtable:

System.Diagnostics.Debug.Assert( (int) bh[1] == 101 );

Reverse lookups, however, are new:

System.Diagnostics.Debug.Assert( (int) bh.ReverseLookup(101) == 1 );

For ease of use and efficiency, BidirHashtable also supports some conversions and additional ways to construct. For example:

public BidirHashtable(IDictionary dict)

This constructor takes a Hashtable or other IDictionary, and initializes the BidirHashtable from it.

Explicit casts are built in for both directions. Be warned, they result in the source object being cloned for the destination object. Still, they make using BidirHashtable, even easier:

Hashtable ht = (Hashtable) bh;
BidirHashtable bh2 = (BidirHashtable) ht;

This function creates a new BidirHashtable which is attached to the input Hashtable. Be careful in using it, but it can be a useful optimization:

public static BidirHashtable Attach(Hashtable ht)

If for any reason, you want the directions swapped, it's just a matter of swapping the internal Hashtable objects. This function accomplishes that:

public void ReverseDirection()

BidirHashtable implements IDictionary, ICollection, IEnumerable, and ICloneable. It does not (yet) implement ISerializable, though it could be added eventually.

Points of interest

Writing this class was one of those rare circumstances where, once it compiled, it basically worked. I did add a few things after the fact, but it's a simple class. You can find more information on my website.

History

  • 08-30-2003 - 1.0 - Initial revision

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here