+4  A: 

I vote for InsertionOrderDictionary. You nailed it.

John Kugelman
Even if InsertionOrderDictionary were the perfectly descriptive name for the concept... nine syllables for a library class makes me cringe.
John Pirie
A: 

As you said in your last paragraph, I think that InsertionOrder(ed)Dict(ionary) is pretty unambiguous; I don't see how it could be interpreted in any way other than that the keys would be returned in the order they were inserted.

Mark Rushakoff
A: 

Is the only difference that allKeys returns keys in a specific order? If so, I would simply add allKeysSorted and allKeysOrderdByInsertion methods to the standard NSDictionary API.

What is the goal of this insertion order dictionary? What benefits does it give the programmer vs. an array?

Steven Canfield
Not, that's not the only difference. I want to track the order of keys continuously, not just generate an array when the user asks for all the keys. The real problem with adding methods to NSDictionary (via a category, I'm assuming) is that you can't add ivars, so this is impossible. Don't forget that -allKeys calls down to -keyEnumerator (an NSDictionary primitive), and that's generally a more efficient way to enumerate keys anyway.
Quinn Taylor
The benefit to the programmer is that they can store things in a dictionary by key like usual, but can also recall the order in which things were added. This might be useful for processing dictionary contents in a specific order where a queue is unnecessary or not quite what you need. Another use could be adapted from Java's LinkedHashMap — you can specify that when keys are accessed or re-inserted, they should move to the end of the list. (This is inefficient since it requires a linear search, but it enables things like evicting least-recently-used items from a cache.)
Quinn Taylor
+1  A: 

Since posting this question, I'm starting to lean towards something like IndexedDictionary or IndexableDictionary. While it is useful to be able to maintain arbitrary key ordering, limiting that to insertion ordering only seems like a needless restriction. Plus, my class already supports indexOfKey: and keyAtIndex:, which are (purposefully) analagous to NSArray's indexOfObject: and objectAtIndex:. I'm strongly considering adding insertObject:forKey:atIndex: which matches up with NSMutableArray's insertObject:atIndex:.

Everyone knows that inserting in the middle of an array is inefficient, but that doesn't mean we shouldn't be allowed to on the rare occasions that it's truly useful. (Besides, the implementation could secretly use a doubly-linked list or any other suitable structure for tracking the ordering if needed...)

The big question: is "indexed" or "indexable" as vague or potentially confusing as "ordered"? Would people think of database indexes, or book indexes, etc.? Would it be detrimental if they assumed it was implemented with an array, or might that simplify user understanding of the functionality?


Edit: This name makes even more sense given the fact that I'm considering adding methods that work with an NSIndexSet in the future. (NSArray has -objectsAtIndexes: as well as methods for adding/removing observers for objects at given indexes.)

Quinn Taylor
I think "indexed" is preferable to "indexable". It's more similar to how things tend to be named in Cocoa (e.g. NSAttributedString rather than NSAttributableString). I do like IndexedDictionary.
Chuck
i think "index" is too strongly associated with databases and efficient searching. If I heard "Oh, its an _indexed_ dictionary", I'd think "Indexed? By what? Value? Really fast key lookup? etc, etc"
Richard Levasseur
Which is funny, because I'm sort of in the opposite camp, where I associate "index" most strongly with arrays. Ironically, in this case, "index" is in fact associated with really fast key lookup. ;-) In either case, duly noted, and thanks for the feedback!
Quinn Taylor
In the context of Cocoa, "index" is always used in the sense of "location in an ordered collection."
Chuck
One unfortunate downside of this name is that back-to-back "d" sounds blend together, so (for example) "NSIndexedDictionary" ends up sounding like "NSIndexDictionary" and bears a misleading resemblance to "NSIndexSet", which is a completely unrelated thing. While "OrderedDictionary" sounds like "OrderDictionary", it won't result in the same confusion with existing Cocoa classes. Plus, "ordered" is marginally easier to say than "indexed". Curse our lazy tongues and repeated hard consonants!! ;-)
Quinn Taylor
A: 

At first glance I'm with the first reply -- InsertionOrderDictionary, though it's a bit ambiguous as to what "InsertionOrder" means at first glance.

What you're describing sounds to me almost exactly like a C++ STL map. From what I understand, a map is a dictionary that has additional rules, including ordering. The STL simply calls it "map", which I think is fairly apt. The trick with map is you can't really give the inheritance a nod without making it redundant -- i.e. "MapDictionary". That's just too redundant. "Map" is a bit too basic and leaves a lot of room for misinterpretation.

Though "CHMap" might not be a bad choice after looking at your documentation link.

Maybe "CHMappedDictionary"? =)

Best of luck.

Edit: Thanks for the clarification, you learn something new every day. =)

slycrel
Actually, maps and dictionaries are the same thing, as I mentioned in the first part of my post. (Unfortunately, C++ added ordering and still calls it "map", probably for brevity, but it causes confusion in cases like yours.) Thus, any combination of "map" and "dictionary" is automatically redundant, and hence not a good name. I can't say that I agree that "insertion order" is vague, though. People seem to "get it", even though I think that terminology is too specific for what the structure supports. :-/
Quinn Taylor
I thought dictionaries and hash maps were the same thing, not regular "maps" which are binary trees.
GMan
A: 

By decoupling the indexed order from the insertion order, doesn't this simply boil down to keeping an array and Dictionary in a single object? I guess my vote for this type of object is IndexedKeyDictionary

In C#:

public class IndexedKeyDictionary<TKey, TValue> { 

  List<TKey> _keys;
  Dictionary<TKey, TValue> _dictionary;
  ...

  public GetValueAtIndex(int index) {
    return _dictionary[_keys[index]];
  }

  public Insert(TKey key, TValue val, int index) {
    _dictionary.Add(key, val);

    // do some array massaging (splice, etc.) to fit the new key
    _keys[index] = key;
  }

  public SwapKeyIndexes(TKey k1, TKey k2) {
    // swap the indexes of k1 and k2, assuming they exist in _keys
  }
}

What would be really cool is indexed values...so we have a way to sort the values and get the new key order. Like if the values were graph coordinates, and we could read the keys (bin names) as we move up/down along the coordinate plane. What would you call that data structure? An IndexedValueDictionary?

Jeff Meatball Yang
Well, it *could* boil down to simple object composition, yes — the details are less relevant (though that won't work as-is for my needs). To do what you're suggesting, NSDictionary (in Cocoa) already has a method called `keysSortedByValueUsingSelector:` which I inherit for free, where "selector" is the name of the method called on each value to compare them. This doesn't maintain the values in a given order in the dictionary itself, but it allows for sorting them however you like on demand, which is probably entirely sufficient for almost all cases.
Quinn Taylor
A: 

What about KeyedArray?

Chris Suter
Hmm, the problem there is that it's fundamentally a dictionary, not an array. (In fact, the structure that organizes the key need not even be an array — a linked list works well, too.) Still, I appreciate the input! :-)
Quinn Taylor
+3  A: 

Strong vote for OrderedDictionary.

The word "ordered" means exactly what you are advertising: that in iterating through a list of items, there is a defined order to selection of those items. "Indexed" is an implementation word -- it talks more to how the ordering is achieved. Index, linked list, tree... the user doesn't care; that aspect of the data structure should be hidden. "Ordered" is the exact word for the additional feature you are offering, regardless of how you get it done.

Further, it seems like the choice of ordering could be at the user's option. Any reason why you couldn't create methods on your datatype that allow the user to switch from, say, alphabetical ordering to insertion-time ordering? In the default case, a user would choose a particular ordering and stick with it, in which case implementation would be no less efficient than if you created specialized subclasses for each ordering method. And in some less-used cases, the developer might actually wish to use any of a number of different orderings for the same data, depending on app context. (I can think of specific projects I've worked on where I would have loved to have such a data structure available.)

Call it OrderedDictionary, because that's precisely what it is. (Frankly, I have more of a problem with the use of the word "Dictionary", because that word heavily implies ordering, where popular implementations of such don't provide it, but that's my pet peeve. You really should just be able to say "Dictionary" and know that the ordering is alphabetical -- because that's what a dictionary IS -- but that argument is too late for existing implementations in the popular languages.) And allow the user to access in what order he chooses.

John Pirie
I see your point but disagree that index is an "implementation word" — I agree with the others, and would say that "array" is as well. Index implies random access, which my dictionary supports; that is, the user can access keys 0 to n-1 "directly". I still think "ordered" is too close to "sorted" for my taste — it implies that the structure (not the user) orders the elements. Swapping ordering is possible, but I already have a SortedDictionary which calls -compare: on each element to determine order. It also adds unneeded complexity. Anything with multiple orderings should utilize composition.
Quinn Taylor
You also have a very valid point about "dictionary" versus a term like "map". Ah, the mistakes of history. Even so, if you think of the term-definition relation, it still makes sense. (One could say that dictionary almost implies a multi-map, since there may be multiple definitions.) Still, I find "dictionary" preferable to "associative array" (PHP) or just plain "hash" (thanks, Ruby). Also, be aware that Objective-C and Cocoa do use some conventions peculiar to the language. Also, Objective-C supports dynamically adding methods via categories, so users can add their own specific orderings.
Quinn Taylor
I guess I often think of something like the Dewey Decimal System when I think of a (non-compsci) index: a classification system that most of all affords quick access, more than defining whether one book is "greater than" or "comes before" another book. Where as you are defining a "comes before" relation amongst your keys. But I see your point too -- and certainly agree that "indexed" is a whole lot better than something like "associative array" (gah).
John Pirie
+3  A: 

I vote OrderedDictionary, for the following reasons:

"Indexed" is never used in Cocoa classes, except in one instance. It always appears as a noun (NSIndexSet, NSIndexPath, objectAtIndex:, etc). There is only one instance when "Index" appears as a verb, which is on NSPropertyDescription's "indexed" property: isIndexed and setIndexed. NSPropertyDescription is roughly analogous to a table column in a database, where "indexing" refers to optimizing to speed up search times. It would therefore make sense that with NSPropertyDescription being part of the Core Data framework, that "isIndexed" and "setIndexed" would be equivalent to an index in a SQL database. Therefore, to call it "IndexedDictionary" would seem redundant, since indices in databases are created to speed up lookup time, but a dictionary already has O(1) lookup time. However, to call it "IndexDictionary" would also be a misnomer, since an "index" in Cocoa refers to position, not order. The two are semantically different.

I understand your concern over "OrderedDictionary", but the precedent has already been set in Cocoa. When users want to maintain a specific sequence, they use "ordered": -[NSApplication orderedDocuments], -[NSWindow orderedIndex], -[NSApplication orderedWindows], etc. So, John Pirie has mostly the right idea.

However, you don't want to make insertion into the dictionary a burden on your users. They'll want to create a dictionary once and then have it maintain an appropriate order. They won't even want to request objects in a specific order. Order specification should be done during initialization.

Therefore, I recommend making OrderedDictonary a class cluster, with private subclasses of InsertionOrderDictionary and NaturalOrderDictionary and CustomOrderDictionary. Then, the user simply creates an OrderedDictionary like so:

OrderedDictionary * dict = [[OrderedDictionary alloc] initWithOrder:kInsertionOrder];
//or kNaturalOrder, etc

For a CustomOrderDictionary, you could have them give you a comparison selector, or even (if they're running 10.6) a block. I think this would provide the most flexibility for future expansion while still maintain an appropriate name.

Dave DeLong
I already debated with Dave previously that CoreData is arguably *not* strictly a Cocoa framework. I like Dave's logic, but I'm really hesitant to introduce my own class cluster just for ordering. I'd like to provide the flexible functionality with as little complexity as possible. I feel that a private class cluster hides too much of the detail in this case — the point of a class cluster is to hide variations of *implementation*, not in *behavior*. You couldn't look at an OrderedDictonary and know in what order the keys would be enumerated. To me, that's a glaring design flaw.
Quinn Taylor
You make great points about the precedent of "ordered" in Cocoa, although I still disagree with everything from "However" on. :-) Any automatic custom ordering will fall under future expansion of SortedDictionary by specifying an NSSortDescriptor, custom selector, etc. There's no need to create a special flavor of SortedDictionary for each desired sort order. While I still like "index" to some degree, agreement with existing implementations (in other languages) and Cocoa conventions trumps personal opinion. Thanks!
Quinn Taylor