-1

I am trying to write a method which will allow me to keep the order of my NSMutableDictionary keys when they are being inserted into the data structure. I know that the NSMutableDictionary works of a hash map, hence not maintaining specific order.

So I need to somehow keep track of the keys which are being inserted into the dictionary, and when retrieving the values from the dictionary, the keys are to be printed(key values) in this same order as when originally inserted. The keys which are inserted into the dictionary are alphanumeric. They just need to be printed out in the same order as when inserted into the NSMutableDictionary.

Can this be achieved? I would like to remain using the NSDictionary Data Structure.

Maff
  • 1,032
  • 4
  • 25
  • 42

2 Answers2

4

NSDictionary (and all its relations) are unordered collections so to "keep its order" makes no sense as there is no order.

If you are wanting to retrieve objects in a specific order then you need to be using an NSArray. (Or NSOrderedSet if uniqueness of hashes is important).

Simple and naive option

If you have a dictionary structure of...

{
    key1:value1,
    key2:value2,
    key3:value3,
    //and so on
}

Then you might be better using something like...

[
    {
        key1:value1
    },
    {
        key2:value2
    },
    {
        key3:value3
    }
]
// i.e. an array of dictionaries

More code but much better option

Or you could create a new collection class as a subclass of NSObject.

In the class you could have something like...

- (void)addObject:(id)object forKey:(id)key
{
    self.dictionary[key] = object;
    [self.array addObject:key];
}

And...

- (id)objectForKey:(key
{
    return self.dictionary[key];
}

And...

- (id)objectAtIndex:(NSUInteger)index
{
    return self.dictionary[self.array[index]];
}

And even...

- (void)removeObjectForKey:(id)key
{
    [self.dictionary removeObjectForKey:key];
    [self.array removeObject:key];
}

You could even make it conform to fast enumeration so you can do...

for (id object in mySuperSpecialCollection) {

}

and make it dispense objects in the order of the array.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • 1
    @Maff can you edit your question. i'm not sure what that code is doing. – Fogmeister Oct 14 '14 at 11:29
  • Updated question above. – Maff Oct 14 '14 at 11:31
  • @Maff well you would have to use your new `SuperSpecialCollection` class. And use a similar method to add the array to it. It's nothing complex it's just a class that has a set and a dictionary. Nothing changes. As it is though, nothing in your code requires it to "keep order". Which bit is the order you need to keep? – Fogmeister Oct 14 '14 at 11:34
  • @Maff also, are you always creating a new words dictionary every time you want to enter something into it? – Fogmeister Oct 14 '14 at 11:35
  • The bit which needs to be ordered is the "subStr" key value, as I use it later in my program to print out the associated values for the key, which require it to be in order. – Maff Oct 14 '14 at 11:38
  • @Maff ok, no worries. Everything in my answer covers all of this already. – Fogmeister Oct 14 '14 at 11:39
  • Ok great! I will try implement this now. So basically, I create this class which is a subclass of NSObject. I then implement all these methods outlined above. Sorry to be a pain, could you modify the above to `.h` and `.m` classes. What happens when I need to iterate through this new custom collection class. – Maff Oct 14 '14 at 11:42
  • @Maff the code in my answer is not complete. It just gives an idea of what you can do. You need to decide (for instance) what happens if you add a key that already exists (etc...) For iterating through it you can either just use a `for(int i=0; i<[myCollection count]; ++i)` or for fast enumeration you can implement the fast enumeration protocol and methods to exploit that. There is no single **right** way to do this and a lot depends on how you want it to behave. You know what you need it to do. So create the object that you need :) – Fogmeister Oct 14 '14 at 11:44
  • @Maff I'm not here to write your code for you. I'm here to help guide you so that you can create it yourself. If you want me to write the code I can send you an invoice if you like :P – Fogmeister Oct 14 '14 at 11:45
  • Haha, appreciate the help mate. I will see what I can come up with. – Maff Oct 14 '14 at 11:47
  • I have updated my method above. If I were to update my code to implement an array of dictionaries, how would I do that? Because you did mention in your answer that I could do that a s solution. – Maff Oct 14 '14 at 12:09
  • @Maff it would be a lot slower. Instead of doing `[blah objectForKey:someKey];` you would have to iterate through the array to find the dictionary that uses that key. Also, there is nothing to stop you adding the same key etc... the custom class is a much better option. – Fogmeister Oct 14 '14 at 12:21
  • I don't know how to write the custom class :( so complex. ahhh – Maff Oct 14 '14 at 12:22
  • @Maff It really isn't complex. If you can write an app that does the stuff you are doing then this should be a walk in the park. Just think about what you need it to do and write the class to do it. You need a dictionary and an array that both work together. That's all. – Fogmeister Oct 14 '14 at 12:24
  • Fogmeister. I Done it. )))) Thank you so much! Collection class was the way! – Maff Oct 14 '14 at 14:14
  • 1
    @Maff Awesome work dude :D Glad you got it working :D – Fogmeister Oct 14 '14 at 14:16
2

Can this be achieved? I would like to remain using the NSDictionary Data Structure.

No. When using instances of NSDictionary the actual class is private. As often with class clusters, it's not possible to subclass NSDictionary and use derived functionality (storing key value pairs).

The best way to go is to set up your own data structure, maybe using an NSOrderedSet and an NSDictionary in conjunction.

Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200
  • Thanks. Would it be possible for you to show me a small programmatic example of how this could be achieved? I am basically storing a `NSString` value for my current NSMutableDictionary `key`, and and `NSArray` for my `key => value`. – Maff Oct 14 '14 at 11:15
  • Well, it's easy: Every time you set an object in the dictionary, you also add the key to the ordered set. When you want the keys in order you just get the keys from the set. – Nikolai Ruhe Oct 14 '14 at 11:19
  • 1
    LOL, yeah I didn't see this before writing my answer but I've done the same thing. – Fogmeister Oct 14 '14 at 11:22