views:

242

answers:

1

I'm in the middle of writing some Cocoa classes to parse ID3 tags from MP3 files. To make them as easy to use as possible, I'm allowing the option to request a tag by the actual ID3 frame id ("TCON", "TPE1", "TALB", etc.) or an equivalent word/phrase ("genre", "artist", "album", etc.)

To store this data, currently I have a reference class which returns an NSDictionary with the frame id's as keys, and word/phrases as objects. As I need to look up definitions in both directions, currently I have a second method which returns the dictionary 'switched round', so the words/phrases are the keys.

My question is whether there is a better way to represent this data. Ideally there would be something similar to NSDictionary, the difference being that both the keys and the values must be unique, and you could look up both an "objectForKey:" and a "keyForObject:"

I could write a class for this myself, but I may lose some of the efficiency from hash tables as described in the NSDictionary documentation... also I'd rather keep the number of classes as low as possible in the overall implementation.

Any ideas? Cheers.

+4  A: 

Funny you should ask this...

Quinn Taylor, the author of the CHDataStructures framework just added a CHBidirectionalDictionary to the framework last week. It allows you to find objects by key, and find keys by object. It's basically a wrapper around two mutable dictionaries, so you're guaranteed the same lookup time as with a regular dictionary.

The only caveat is that both the object and key must both conform to the NSCopying protocol.

Dave DeLong
wipolar
@wipolar: It looks like CHBidirectionalDictionary only depends on CHLockableDictionary and Util.h, so you don't have to link in a whole framework, just grab those files and plunk the into your project. Much faster than writing it yourself.
Chuck
Thanks, Dave. Also note that it might be conceptually easier to call `-inverseDictionary` and call `-objectForKey:` on that (rather than `-keyForObject:`, although that is supported). An inverse bidirectional dictionary points to the same two dictionary references, but in reversed order. Thus, there is only the additional overhead for a second containing object, not for new dictionaries. It really comes down to what makes more sense to you.
Quinn Taylor
@Chuck is correct. If you really want to minimize the class footprint, you could even push the common functionality of CHLockableDictionary and Util.h down into CHBiderectionalDictionary for your own use. One of the beauties of open source. :-) Of course, the footprint of the framework itself is rather small, and the work (and testing!) has already been done for you. http://dysart.cs.byu.edu/CHDataStructures/coverage/source/ Either way, good luck!
Quinn Taylor
@wipolar One thing to remember is that NSMutableDictionary copies keys on insertion, so inserting keys->values in one and values->keys in another will result in twice as many objects, since one will have as keys copies of the values in the other, and vice versa. My dictionary class uses CFMutableDictionaryRef so I can manually control when the keys are copied. Not a HUGE waste of memory, but something to be aware of. It wouldn't be too hard to roll everything into one class to minimize your footprint if that's your thing.
Quinn Taylor