Insert NSMutableDictionary with NSDictionaries - objective-c

I tried to insert NSDictionary's in a NSMutableDictionary. There is no error but it won't work, it remains empty.
Here's my code:
NSMutableDictionary *einnahmen = [[NSMutableDictionary alloc] initWithCapacity:20];
NSArray *objects = [NSArray arrayWithObjects:
name,
[NSNumber numberWithInt: x],
[NSNumber numberWithInt: y],
[NSNumber numberWithInt: z],
nil];
NSArray *keys = [NSArray arrayWithObjects:
#"name",
#"startJahr",
#"zins",
#"entnahmefaehig",
nil];
NSDictionary *entry = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
[einnahmen setObject:entry forKey:#"name"]; //seems not to work
After [einnahmen setObject:entry the Debugger shows this:

I have solved this problem. The following code was in the wrong init-method:
NSMutableDictionary *einnahmen =
[[NSMutableDictionary alloc] initWithCapacity:20];
The compiler should show a error.

Related

Get NSArray of NSDictionary keys sorted by Value then Key

Say I have a dictionary with keys (words) and values (scores) as follows:
GOD 8
DONG 16
DOG 8
XI 21
I would like to create an NSArray of dictionary keys (words) that is sorted first by score then alphabetically. From the example above this would be:
XI
DONG
DOG
GOD
What's the best way to achieve this?
I would use and NSArray of NSDictionaries and then implement it using NSSortDescriptors:
NSSortDescriptor *sdScore = [NSSortDescriptor alloc] initWithKey:#"SCORE" ascending:NO];
NSSortDescriptor *sdName = [NSSortDescriptor alloc] initWithKey:#"NAME" ascending:YES];
NSArray *sortedArrayOfDic = [unsortedArrayOfDic sortedArrayUsingDescriptors:[NSArray arrayWithObjects: sdScore, sdName, nil]];
Carlos' answer is the correct one I'm just posting the full code I ended up with just in case anyone is interested:
NSDictionary *dataSourceDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:8], #"GOD",
[NSNumber numberWithInt:16], #"DONG",
[NSNumber numberWithInt:8], #"DOG",
[NSNumber numberWithInt:21], #"XI", nil];
NSSortDescriptor *scoreSort = [NSSortDescriptor sortDescriptorWithKey:#"SCORE" ascending:NO];
NSSortDescriptor *wordSort = [NSSortDescriptor sortDescriptorWithKey:#"WORD" ascending:YES];
NSArray *sorts = [NSArray arrayWithObjects:scoreSort, wordSort, nil];
NSMutableArray *unsortedArrayOfDict = [NSMutableArray array];
for (NSString *word in dataSourceDict)
{
NSString *score = [dataSourceDict objectForKey:word];
[unsortedArrayOfDict addObject: [NSDictionary dictionaryWithObjectsAndKeys:word, #"WORD", score, #"SCORE", nil]];
}
NSArray *sortedArrayOfDict = [unsortedArrayOfDict sortedArrayUsingDescriptors:sorts];
NSDictionary *sortedDict = [sortedArrayOfDict valueForKeyPath:#"WORD"];
NSLog(#"%#", sortedDict);
Related: NSDictionary split into two arrays (objects and keys) and then sorted both by the objects array (or a similar solution)
I couldn't test this because i'm not on a Mac (sorry if I misspelled something), but:
NSDictionary *dic1 = [NSDictionary dictionaryWithObjectsAndKeys:#"GOD", #"WORD", [NSNumber numberWithInt:8], #"SCORE", nil];
NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys:#"DONG", #"WORD", [NSNumber numberWithInt:16], #"SCORE", nil];
NSDictionary *dic3 = [NSDictionary dictionaryWithObjectsAndKeys:#"DOG", #"WORD", [NSNumber numberWithInt:8], #"SCORE", nil];
NSDictionary *dic4 = [NSDictionary dictionaryWithObjectsAndKeys:#"XI", #"WORD", [NSNumber numberWithInt:21], #"SCORE", nil];
NSSortDescriptor *scoreSort = [NSSortDescriptor sortDescriptorWithKey:#"SCORE" ascending:NO];
NSSortDescriptor *wordSort = [NSSortDescriptor sortDescriptorWithKey:#"WORD" ascending:YES];
NSArray *sortedArrayOfDic = [[NSArray arrayWithObjects:dic1, dic2, dic3, dic4, nil] sortedArrayUsingDescriptors:[NSArray arrayWithObjects:scoreSort, wordSort, nil]];
NSLog(#"%#", [sortedArrayOfDict valueForKeyPath:#"WORD"]);
This would do the same but a bit reduced and avoiding an iteration.

How to sort an NSArray in alphabetical order with numbers first

I have a small doubt that is I have an NSArray which contains the following 4 objects:
Genesis, 1 Kings, leviticus, 2 Kings
I want to sort this array in dictionary order like i want an expected output like this
1 Kings, 2 Kings, Genesis, leviticus
How can this be achieved?
Go to this link:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html#//apple_ref/doc/uid/20000132-SW5
This is Apple documentation and your problem is solved over there.
Check out the example.
//First create the array of dictionaries
NSString *last = #"lastName";
NSString *first = #"firstName";
NSMutableArray *array = [NSMutableArray array];
NSArray *sortedArray;
NSDictionary *dict;
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Jo", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joe", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joe", first, #"Smythe", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joanne", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Robert", first, #"Jones", last, nil];
[array addObject:dict];
//Next we sort the contents of the array by last name then first name
// The results are likely to be shown to a user
// Note the use of the localizedCaseInsensitiveCompare: selector
NSSortDescriptor *lastDescriptor =[[NSSortDescriptor alloc] initWithKey:last
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *firstDescriptor =
[[NSSortDescriptor alloc] initWithKey:first
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
sortedArray = [array sortedArrayUsingDescriptors:descriptors];
This code is an example from Apple documentation.
You can sort an array of NSString alphabetically like this:
NSArray *sortedArray = [myArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];

Is there a more elegant way of finding unique NSDictionary keys within an NSArray?

Aim: To obtain an NSArray containing unique keys for given NSDictionary(s) using elegant code
Example Code with Current Working Solution:
NSArray *data = [[NSArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], #"a", [NSNumber numberWithInt:2], #"b", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], #"b", [NSNumber numberWithInt:4], #"c", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:5], #"a", [NSNumber numberWithInt:6], #"c", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:7], #"b", [NSNumber numberWithInt:8], #"a", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:8], #"c", [NSNumber numberWithInt:9], #"b", nil],
nil];
// create an NSArray of all the dictionary keys within the NSArray *data
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for (int i=0; i<[data count]; i++) {
[setKeys addObjectsFromArray:[[data objectAtIndex:i] allKeys]];
}
NSArray *arrayKeys = [setKeys allObjects];
NSLog(#"arrayKeys: %#", arrayKeys);
Which returns the desired array of keys:
2012-06-11 16:52:57.351 test.kvc[6497:403] arrayKeys: (
a,
b,
c
)
Question: Is there a more elegant way of approaching this? Surely there must be some KVC approach that can get all the keys without having to iterate through the array? I've been looking at Apple Developer Documentation and can't see a solution. Any ideas? (looking at purely elegance of code rather than performance).
Normally you could use KVC by doing something like this:
NSArray *uniqueKeys = [data valueForKeyPath:#"#distinctUnionOfArrays.allKeys";
However NSDictionary overrides the valueForKey: selector which is used by the KVC internals, so this will not work correctly.
The documentation for NSDictionary's valueForKey: method tells us that:
If key does not start with “#”, invokes objectForKey:. If key does start with “#”, strips the “#” and invokes [super valueForKey:] with the rest of the key.
So we just insert an # before allKeys:
NSArray *uniqueKeys = [data valueForKeyPath:#"#distinctUnionOfArrays.#allKeys"];
And we get what we want:
(lldb) po [data valueForKeyPath:#"#distinctUnionOfArrays.#allKeys"]
(id) $14 = 0x07bb2fc0 <__NSArrayI 0x7bb2fc0>(
c,
a,
b
)
This is less ugly, and possibly marginally faster, I suppose:
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for (NSDictionary* dict in data) {
for (id key in [dict keyEnumerator]) {
[setKeys addObject:key];
}
}
But you're not doing a particularly common operation, so I wouldn't expect to find some incredibly elegant method. If that's what you want, go learn Haskell.
You could try this:
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for(NSDictionary *dict in data) {
[setKeys addObjectsFromArray:[dict allKeys]];
}
NSArray *arrayKeys = [setKeys allObjects];
If you prefer blocks you could use this:
[data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[setKeys addObjectsFromArray:[obj allKeys]];
}];

Why is the error with this code?

I have:
boardValue = [NSNumber numberWithInteger: 2];
NSDictionary * dict = [NSDictionary dictionaryWithValuesForKeys: #"sample", #"word", boardValue , #"value", nil];
This is very similar to the following example:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: #"value1", #"key1", #"value2", #"key2", nil];
from Apple documentations at:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsdictionary_Class/Reference/Reference.html
I get the error "too many arguments to method call, expect 1, have 5". What is the problem?
dictionaryWithValuesForKeys: takes an array as an argument, not a variable list of arguments.
(Also, I believe it's an instance method, not a class method, so [NSDictionary dictionaryWithValuesForKeys:args]` won't work.)
Notice your code compared to the documentation. You want to call...
boardValue = [NSNumber numberWithInteger: 2];
NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys: #"sample", #"word", boardValue , #"value", nil];

Can NSArray hold NSDictionary in Objective-C/

Can each index of array hold the NSDictionary?
Thank You.
Yes, the value of an NSArray can resolve to an object identifier for an NSDictionary. However, the array doesn't "hold" the NSDictionary, nor can the index of an NSArray be an NSDictionary. An index from an Array is always an integer value.
An NSArray can hold any type of object, so yes, putting an NSDictionary in an NSArray works just fine.
You sure can, here is an example:
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:
#"value1", #"key1", #"value2", #"key2", nil];
NSDictionary *dict2 = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Billy", #"Goat", #"Rover", #"Dog", nil];
NSArray *arrayWithDictionaries = [[NSArray alloc] initWithObjects:
dict1, dict2, nil];
[dict1 release];
[dict2 release];