anon
anon

Reputation:

Algorithm: Keeping count of key/value pair in NSDictionary

Being new to Cocoa, and probably not knowing all of the potential classes available that already have this functionality neatly wrapped in an OO class, here's an algorithm inquiry. What's the best bet to count how many times a particular key occurs in an array of multiple NSDictionary instances?

Essentially my data structure (in this case an NSArray) might contain several NSDictionary instances at any given time, each one having the same keys, potentially different values. Some values repeat. I'd like to be able to know how many times a particular key/value appears. Example:

{
  foo => 1,
  bar => 2
}
{
  foo => 1,
  bar => 3
}
{
  foo => 2,
  bar => 1
}

In this case I'm interested that foo=>1 occured 2 times and foo=>2 occured 1 time. Is building an instance of NSCountedSet the best way to go about this? Perhaps a C linked-list?

Upvotes: 1

Views: 9309

Answers (3)

Peter Hosey
Peter Hosey

Reputation: 96353

NSCountedSet *keyCounts = [NSCountedSet set];
for (NSDictionary *dict in myDictionaries)
    [keyCounts unionSet:[NSSet setWithArray:[dict allKeys]]];

Upvotes: 1

James Eichele
James Eichele

Reputation: 119164

NSDictionary * dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:
                        [NSNumber numberWithInt:1], @"foo",
                        [NSNumber numberWithInt:2], @"bar", nil];
NSDictionary * dict2 = [[NSDictionary alloc] initWithObjectsAndKeys:
                        [NSNumber numberWithInt:1], @"foo",
                        [NSNumber numberWithInt:3], @"bar", nil];
NSDictionary * dict3 = [[NSDictionary alloc] initWithObjectsAndKeys:
                        [NSNumber numberWithInt:2], @"foo",
                        [NSNumber numberWithInt:1], @"bar", nil];
NSArray * arrayOfDictionaries = [[NSArray alloc] initWithObjects:
                                 dict1, dict2, dict3, nil];

// count all keys in an array of dictionaries (arrayOfDictionaries):

NSMutableDictionary * countKeys = [[NSMutableDictionary alloc] initWithCapacity:0];
NSCountedSet * counts = [[NSCountedSet alloc] initWithCapacity:0];

NSArray * keys;
NSString * pairString;
NSString * countKey;
for (NSDictionary * dictionary in arrayOfDictionaries)
{
    keys = [dictionary allKeys];
    for (NSString * key in keys)
    {
        pairString = [NSString stringWithFormat:@"%@->%@", key, [dictionary valueForKey:key]];
        if ([countKeys valueForKey:pairString] == nil)
        {
            [countKeys setValue:[NSString stringWithString:pairString] forKey:pairString];
        }
        countKey = [countKeys valueForKey:pairString];
        { [counts addObject:countKey]; }
    }
}

NSLog(@"%@", counts);

[counts release];
[countKeys release];

[arrayOfDictionaries release];
[dict1 release];
[dict2 release];
[dict3 release];

Upvotes: 2

Brian C. Lane
Brian C. Lane

Reputation: 4171

You may want to rethink how you are structuring your data. I'd track something like this while adding to the NSArray instead of trying to discover it at a later time. You might create a new class to handle adding and removing the data so that you can keep your own counts of the data.

Upvotes: 4

Related Questions