Skip to content

Instantly share code, notes, and snippets.

@aspitz
Created July 31, 2013 13:49
Show Gist options
  • Save aspitz/6122137 to your computer and use it in GitHub Desktop.
Save aspitz/6122137 to your computer and use it in GitHub Desktop.
A dictionary that keeps track of the order that elements were added to it
@interface OrderedDictionary : NSObject <NSCopying, NSCoding>{
NSMutableDictionary *_dictionary;
NSMutableArray *_array;
}
@property (readonly) NSUInteger count;
- (id)init;
- (id)initWithCapacity:(NSUInteger)capacity;
+ (id)dictionary;
+ (id)dictionaryWithCapacity:(NSUInteger)capacity;
- (void)setObject:(id)object forKeyedSubscript:(id<NSCopying>)aKey;
- (id)objectForKeyedSubscript:(id)key;
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)removeObjectForKey:(id)aKey;
- (void)removeAllObjects;
- (NSArray *)allKeys;
- (NSArray *)allValues;
- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block;
- (void)enumerateKeysUsingBlock:(void (^)(id key, NSUInteger idx, BOOL *stop))block;
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block;
- (BOOL)isEqualToOrderedDictionary:(OrderedDictionary *)orderedDictionary;
@end
//
// OrderedDictionary.m
// OrderedDictionary
//
// Created by Ayal Spitz on 3/25/13.
// Copyright (c) 2013 Ayal Spitz. All rights reserved.
//
#import "OrderedDictionary.h"
@implementation OrderedDictionary
- (id)init{
self = [super init];
if (self) {
_dictionary = [NSMutableDictionary dictionary];
_array = [NSMutableArray array];
}
return self;
}
- (id)initWithCapacity:(NSUInteger)capacity{
self = [super init];
if (self) {
_dictionary = [NSMutableDictionary dictionaryWithCapacity:capacity];
_array = [NSMutableArray arrayWithCapacity:capacity];
}
return self;
}
#pragma mark -
+ (id)dictionary{
return [[OrderedDictionary alloc]init];
}
+ (id)dictionaryWithCapacity:(NSUInteger)capacity{
return [[OrderedDictionary alloc]initWithCapacity:capacity];
}
#pragma mark - NSCopying methods
- (id)copyWithZone:(NSZone *)zone{
OrderedDictionary *dictionary = [[OrderedDictionary alloc]initWithCapacity:self.count];
dictionary->_dictionary = [self->_dictionary mutableCopyWithZone:zone];
dictionary->_array = [self->_array mutableCopyWithZone:zone];
return dictionary;
}
#pragma mark - NSCoding methods
#define kDictionaryKey @"Dictionary"
#define kArrayKey @"Array"
- (id)initWithCoder:(NSCoder *)decoder{
self = [super init];
if (self) {
_dictionary = [decoder decodeObjectForKey:kDictionaryKey];
_array = [decoder decodeObjectForKey:kArrayKey];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder{
[encoder encodeObject:_dictionary forKey:kDictionaryKey];
[encoder encodeObject:_array forKey:kArrayKey];
}
#pragma mark - Set methods
- (void)setObject:(id)object forKeyedSubscript:(id<NSCopying>)aKey{
id value = _dictionary[aKey];
if (object != nil){
// if value isn't nil that means we are changing a key/value so we're changing it's index
if (value != nil){
[_array removeObject:aKey];
}
[_array addObject:aKey];
_dictionary[aKey] = object;
} else {
[_array removeObject:aKey];
[_dictionary removeObjectForKey:aKey];
}
}
#pragma mark - Get Methods
- (id)objectForKeyedSubscript:(id)key{
return _dictionary[key];
}
- (id)objectAtIndexedSubscript:(NSUInteger)idx{
return self[_array[idx]];
}
#pragma mark - Remove Methods
- (void)removeObjectForKey:(id)aKey{
self[aKey] = nil;
}
- (void)removeAllObjects{
[_dictionary removeAllObjects];
[_array removeAllObjects];
}
#pragma mark -
- (NSUInteger)count{
return _dictionary.count;
}
#pragma mark - Keys and Objects methods
- (NSArray *)allKeys{
return [_array copy];
}
- (NSArray *)allValues{
NSMutableArray *objects = [NSMutableArray arrayWithCapacity:_array.count];
[_array enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
[objects addObject:self[key]];
}];
return objects;
}
- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block{
[_array enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
id obj = self[key];
block(key, obj, stop);
}];
}
- (void)enumerateKeysUsingBlock:(void (^)(id key, NSUInteger idx, BOOL *stop))block{
[_array enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
block(key, idx, stop);
}];
}
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block{
[_array enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
id obj = self[key];
block(obj, idx, stop);
}];
}
#pragma mark - Equality methods
- (BOOL)isEqualToOrderedDictionary:(OrderedDictionary *)orderedDictionary{
return ([self.allKeys isEqualToArray:orderedDictionary.allKeys] && [self.allValues isEqualToArray:orderedDictionary.allValues]);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment