Is there a way for find how many keys are currently in a NSMutableDictionary? - objective-c

Just curious if there is a way to find the number of keys in a NSMutableDictionary? Also is there a way to access each key in turn and find its value, or do I need to access the data manually via the predefined keys?
(i.e.)
myTown = [cryo objectForKey: #"town"];
myZip = [cryo objectForKey: #"HT6 4HT"];
myEmail = [cryo objectForKey: #"pink#grapefruit.xxx"];
I guess I am thinking using a wildcard or something for the key?
gary

-[NSMutableDictionary count]

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSLog(#"%d", [[dict allKeys] count]);
[dict allKeys] gives you the list of all the current keys.

Related

Xcode Sort Arrays by size in objectKey

So I have an object of type 'id friendData'stored in a singleton class 'coreData' from which I produce a mutable array for object key "data" as follows:
NSMutableArray *friends = [_coreData.friendData objectForKey:#"data"];
I then establish a dictionary which takes user parameters using keys "id" and "name", as well as a NSMutable array *scores which is obtained by a HTTP post request.
NSMutableDictionary *directory = [NSMutableDictionary dictionary];
[directory setObject:[friends valueForKey:#"id"] forKey:#"id"];
[directory setObject:[friends valueForKey:#"name"] forKey:#"name"];
[directory setObject:scores forKey:#"score"];
I am wanting to order object scores from highest to lowest for the purposes of a scoreboard, but it's my understanding that rearranging within a dictionary won't maintain the same order for the objects 'id' and 'name'. Is this infact possible, or is it better to reintroduce the *scores object to *friends under an appropriate key, and apply a sort algorith? If so, how? Any help, including example code and possible sort procedure would be great!
Just sort scores array before setting it into the dictionary. I am not sure what are exactly the kind of objects you have in scores, Im guessing they are plain NStrings. In that case this should work:
NSArray *sortedArray = [scores sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSInteger first = [(NSString *)a intValue];
NSDate *second = [(NSString *)b intValue];
return [first compare:second];
}];
NSMutableDictionary *directory = [NSMutableDictionary dictionary];
[directory setObject:[friends valueForKey:#"id"] forKey:#"id"];
[directory setObject:[friends valueForKey:#"name"] forKey:#"name"];
[directory setObject:sortedScoresArray forKey:#"score"];

NSDictionary order of keys and values

I know that in NSDictionary, there are no guarantees about the order of items when enumerating.
However, is it safe to expect that [[myDictionary allValues] objectAtIndex:index] will always be the matching value of key [[myDictionary allKeys] objectAtIndex:index]? (supposing that the dictionary is immutable).
Even if there is a very good chance that the two are going to be in the same order, Apple can change it at any time, because there is simply no guarantee of the order.
If you need two NSArrays, one with keys and one with values, with "parallel" indexes, a better approach to this would be building these arrays yourself by enumerating key-value pairs of the dictionary, and adding them to the two arrays that you build:
NSMutableArray *keys = [NSMutableArray array];
NSMutableArray *vals = [NSMutableArray vals];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[keys addObject:key];
[vals addObject:obj];
}];
You can also get keys separately, and then get values in an array with parallel indexing by calling objectsForKeys:notFoundMarker: method:
NSArray *keys = [dict allKeys];
// In the call below, the marker [NSNull null] will not be used, because we know
// that all keys will be present in the dictionary.
NSArray *vals = [dict objectsForKeys:keys notFoundMarker:[NSNull null]];

How can I change all the values for keys in a plist at once to one particular value?

I have a plist with multiple keys. Each of the values for the keys is either "N" or "Y".
I don't have a problem going in one by one and changing the values. But is there a way to change every value for keys in a plist to one value? It would really shorten my code.
Current code changes one value for one key in a plist like this:
NSString *newValue;
newValue = #"Y";
[manufacturerDictionary setObject:[NSString stringWithString:newValue]
forKey:manufacturerName];
[manufacturerDictionary writeToFile: path atomically:YES];
[manufacturerDictionary release];
Based on your code, I'm assuming your plist contains a single archived NSDictionary as the root object. How about this:
NSString *newValue = #"Y";
NSArray *allKeys = [manufacturerDictionary allKeys];
for (NSString *key in allKeys)
{
[manufacturerDictionary setObject:newValue forKey:key];
}
[manufacturerDictionary writeToFile:path atomically:YES];
[manufacturerDictionary release];
for (NSString *key in allKeys) uses fast enumeration to enumerate each key that exists in the dictionary.

Cocoa: Any downside to using NSSet as key in NSMutableDictionary?

Is there any downside to using NSSet as key in NSMutableDictionary, any gotchas to be aware of, any huge performance hits?
I think keys are copied in Cocoa containers, does it mean NSSet is copied to dictionary? Or is there some optimization that retains the NSSet in this case?
Related to Can a NSDictionary take in NSSet as key?
Example code:
NSMutableDictionary * dict = [NSMutableDictionary dictionary];
NSSet * set;
set = [NSSet setWithObjects:#"a", #"b", #"c", #"d", nil];
[dict setObject:#"1" forKey:set];
set = [NSSet setWithObjects:#"b", #"c", #"d", #"e", nil];
[dict setObject:#"2" forKey:set];
id key;
NSEnumerator * enumerator = [dict keyEnumerator];
while ((key = [enumerator nextObject]))
NSLog(#"%# : %#", key, [dict objectForKey:key]);
set = [NSSet setWithObjects:#"c", #"b", #"e", #"d", nil];
NSString * value = [dict objectForKey:set];
NSLog(#"set: %# : key: %#", set, value);
Outputs:
2009-12-08 15:42:17.885 x[4989] (d, e, b, c) : 2
2009-12-08 15:42:17.887 x[4989] (d, a, b, c) : 1
2009-12-08 15:42:17.887 x[4989] set: (d, e, b, c) : key: 2
I think keys are copied in Cocoa containers, does it mean NSSet is copied to dictionary? Or is there some optimization that retains the NSSet in this case?
NSDictionaries do copy their keys.
An immutable set will probably respond to copy by returning itself retained, making the “copy” practically free.
A mutable set will respond to copy by returning a copy of itself, which is why using mutable objects as keys is generally a bad idea (you won't be able to find the original after mutating it because it no longer compares equal to the key in the dictionary).
Ooh. Yes. There is a big performance downside. It happens that -[NSSet hash] is implemented as [set count]. That means that if all your sets have 2 objects, say, then they all have the same hash, and the collection will perform very poorly.

Sorting NSDictionary

I was wondering if someone can show me how to sort an NSDictionary; I want to read it starting from the last entry, since the key is Date + Time and I want to be able to append it to an NSMutableString. I was able to read it using an enumerator but I don't get the results I want.
Thanks
For your requirements the easiest way is to create a new array from the keys, sort that, then use the array to reference items from the original dictionary.
(Note myComparison is your own method that will compare two keys).
NSMutableArray* tempArray = [NSMutableArray arrayWithArray:[myDict allKeys]];
[tempArray sortedArrayUsingSelector:#selector(myComparison:)];
for (Foo* f in tempArray)
{
Value* val = [myDict objectForKey:f];
}
I've aggregated some of the other suggestions on StackOverflow on sorting an NSDictionary into something very compact that will sort alphabetically. I have a Plist file in 'path' that I load in to memory and want to dump.
NSDictionary *glossary = [NSDictionary dictionaryWithContentsOfFile: path];
NSArray *array1 = [[glossary allKeys] sortedArrayUsingDescriptors:#[ [NSSortDescriptor sortDescriptorWithKey:#"" ascending:YES selector:#selector(localizedStandardCompare:)] ]];
for ( int i=0; i<array1.count; i++)
{
NSString* key = [array1 objectAtIndex:i];
NSString* value = [glossary objectForKey:key];
NSLog(#"Key=%#, Value=%#", key, value );
}