Nsdictionary With Ordered Keys

Are keys and values in an NSDictionary ordered?

No, they are not ordered. As long as you don't add or remove any elements from the dictionary, they will remain in the same order, but as soon as you add or remove an element, the new order will be completely different.

If you need the keys/values to be ordered, use an NSArray (or some other ordered data structure) instead.

Getting NSDictionary keys sorted by their respective values

The NSDictionary Method keysSortedByValueUsingComparator: should do the trick.

You just need a method returning an NSComparisonResult that compares the object's values.

Your Dictionary is

NSMutableDictionary * myDict;

And your Array is

NSArray *myArray;

myArray = [myDict keysSortedByValueUsingComparator: ^(id obj1, id obj2) {

if ([obj1 integerValue] > [obj2 integerValue]) {

return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 integerValue] < [obj2 integerValue]) {

return (NSComparisonResult)NSOrderedAscending;
}

return (NSComparisonResult)NSOrderedSame;
}];

Just use NSNumber objects instead of numeric constants.

BTW, this is taken from:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Dictionaries.html

Sort NSDictionary keys and values in array

The problem is that dictionaries do not have indexes. Only arrays have an index. So the dictionary will guarantee you to respect the key/value pairs, but you have no control on how those information are stored. As a matter of fact, if you save the content to a text file, you may see the order changing each time.

If you really want to use something that feels like a numeric index in a dictionary, use a number as a key (you will have to covert it from string to number if you plan to use it in a for/next loop for sorting). Dictionaries can contain arrays, so each key can point to an array as value.

Keeping a specific Order of an NSMutableDictionary Object

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.

Maintaining the order while iterating a NSDictionary

NSMutableDictionary is not ordered. There is nothing you can do to guarantee the order of keys because NSDictionary makes no attempt to preserve any particular ordering. To go over a dictionary in a particular order, you have to make an NSArray of the keys that is in the order you want, then iterate that and fetch the corresponding values.

NSDictionary getting sorted alphabetically

NSDictionary is not ordered by default. It will always be without any order. To create an ordered dictionary, you will need to override the existing form of the Data structure. You can read This tutorial to achieve your end.

To summarize the tutorial (Because everyone hates link-only answers and links can die any time):

NSDictionary stores its keys in a hash table, which is unordered by design. Since this lack of order is fundamental to the hash table storeage, you have to perform subclassing of NSMutableDictionary (and hence reimplementation of the storage).

In your .h file

//
// OrderedDictionary.h
// OrderedDictionary
//
// Created by Matt Gallagher on 19/12/08.
// Copyright 2008 Matt Gallagher. All rights reserved.
//
// Permission is given to use this source code file without charge in any
// project, commercial or otherwise, entirely at your risk, with the condition
// that any redistribution (in part or whole) of source code must retain
// this copyright and permission notice. Attribution in compiled projects is
// appreciated but not required.
//

#import <Cocoa/Cocoa.h>

@interface OrderedDictionary : NSMutableDictionary
{
NSMutableDictionary *dictionary;
NSMutableArray *array;
}

- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex;
- (id)keyAtIndex:(NSUInteger)anIndex;
- (NSEnumerator *)reverseKeyEnumerator;

@end

In your .m file:

//
// OrderedDictionary.m
// OrderedDictionary
//
// Created by Matt Gallagher on 19/12/08.
// Copyright 2008 Matt Gallagher. All rights reserved.
//
// Permission is given to use this source code file without charge in any
// project, commercial or otherwise, entirely at your risk, with the condition
// that any redistribution (in part or whole) of source code must retain
// this copyright and permission notice. Attribution in compiled projects is
// appreciated but not required.
//

#import "OrderedDictionary.h"

NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
{
NSString *objectString;
if ([object isKindOfClass:[NSString class]])
{
objectString = (NSString *)[[object retain] autorelease];
}
else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
{
objectString = [(NSDictionary *)object descriptionWithLocale:locale indent:indent];
}
else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
{
objectString = [(NSSet *)object descriptionWithLocale:locale];
}
else
{
objectString = [object description];
}
return objectString;
}

@implementation OrderedDictionary

- (id)init
{
return [self initWithCapacity:0];
}

- (id)initWithCapacity:(NSUInteger)capacity
{
self = [super init];
if (self != nil)
{
dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
array = [[NSMutableArray alloc] initWithCapacity:capacity];
}
return self;
}

- (void)dealloc
{
//This method is pre-ARC. Manual Release commands don't work now.
//[dictionary release];
//[array release];
//[super dealloc];
}

- (id)copy
{
return [self mutableCopy];
}

- (void)setObject:(id)anObject forKey:(id)aKey
{
if (![dictionary objectForKey:aKey])
{
[array addObject:aKey];
}
[dictionary setObject:anObject forKey:aKey];
}

- (void)removeObjectForKey:(id)aKey
{
[dictionary removeObjectForKey:aKey];
[array removeObject:aKey];
}

- (NSUInteger)count
{
return [dictionary count];
}

- (id)objectForKey:(id)aKey
{
return [dictionary objectForKey:aKey];
}

- (NSEnumerator *)keyEnumerator
{
return [array objectEnumerator];
}

- (NSEnumerator *)reverseKeyEnumerator
{
return [array reverseObjectEnumerator];
}

- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex
{
if (![dictionary objectForKey:aKey])
{
[self removeObjectForKey:aKey];
}
[array insertObject:aKey atIndex:anIndex];
[dictionary setObject:anObject forKey:aKey];
}

- (id)keyAtIndex:(NSUInteger)anIndex
{
return [array objectAtIndex:anIndex];
}

- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
NSMutableString *indentString = [NSMutableString string];
NSUInteger i, count = level;
for (i = 0; i < count; i++)
{
[indentString appendFormat:@" "];
}

NSMutableString *description = [NSMutableString string];
[description appendFormat:@"%@{\n", indentString];
for (NSObject *key in self)
{
[description appendFormat:@"%@ %@ = %@;\n",
indentString,
DescriptionForObject(key, locale, level),
DescriptionForObject([self objectForKey:key], locale, level)];
}
[description appendFormat:@"%@}\n", indentString];
return description;
}

@end

You can Download Matt Gallagher's orderedDictionary here.



Related Topics



Leave a reply



Submit