Access object of Nested NSDictionary - objective-c

Is there a way to directly access an inner-Dictionary of an outer Dictionary in Objective-C? For example, I have key to an object which is part of inner dictionary, Is there any way to directly access object from that key.
GameDictionary {
Indoor_Game = { "game1" = chess; "game2" = video_Game; "game3" = poker; };
OutDoor_Game = { "game4" = cricket; "game5" = hockey; "game6" = football; };
};
I have a key "game4", but I don't know in which dictionary object of this key is present, currently I have to search in each dictionary for object, the code which I am using is:
NSString* gameName = nil;
NSString* gameKey = #"game4";
NSArray* gameKeys = [GameDictionary allKeys];
for (int index = 0; index < [gameKeys count]; index ++) {
NSDictionary* GameType = [GameDictionary objectForKey:[gameKeys objectAtIndex:index]];
if ([GameType objectForKey:gameKey]) {
gameName = [GameType objectForKey:gameKey];
break;
}
}
Is their any easy way to access directly to the inner dictionary instead of for loops.

valueForKeyPath looks like what you want.
[GameDictionary valueForKeyPath:#"OutDoor_Game"]
//would return a dictionary of the games - "game4" = cricket; "game5" = hockey; "game6" = football;
[GameDictionary valueForKeyPath:#"OutDoor_Game.game4"]
//would return cricket
https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html

Related

How get a key value in NSMutableArray?

A NSMutableArray called arrayDB, and it gets data from server by using AFNetworking, like this
[self.arrayDB addObjectsFromArray:[responseObject objectForKey:#"list"]];
NSLog(#"print:%#",self.arrayDB);
And the result like this.
print:(
{
id = 10;
key = 7707eca6ea4d2db923c8b7b4e6ec094c;
},
{
id = 9;
key = 7aaf962bc4df61a3b44c544c58fc6c82;
},
{
id = 7;
key = ce9d9e99a96d6417c6b34321c820c4c0;
},
{
id = 6;
key = 6086663465e5813d08f862eb443e2623;
},
{
id = 4;
key = 5d9519dd7de26f0139d6028fb83a4ead;
}
)
And now, I use sql statement to describe my needs, select key from arrayDB where id=10, how can I write in objective-C?
You can use NSPredicate like this:
NSArray *myArray = [self.arrayDB filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(id == %#)", #"10"]];

Pushing data in existing Multidimensional NSMutableDictionary Objective c

I have a record of 100 Electronic items with Categories in database, with every request I load 20 records in Table View. I want to merge 2 arrays into 3rd array
E.g.
1) NSMutableDictionary *prevResultSet;
2) NSMutableDictionary *newResultSet;
3) NSMutableDictionary *finalArray;
I tried using addEntriesFromDictionary but it overwrites the duplicate key instead of merging.
_finalArray = [[NSMutableDictionary alloc] init];
[_finalArray addEntriesFromDictionary:_prevResultSet];
[_finalArray addEntriesFromDictionary:_newResultSet];
_prevResultSet = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = Samsung;
},
{
rate = "15,000";
type = Sony;
},
);
_newResultSet = {
LCD = (
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Current Output: (After using addEntriesFromDictionary:)
_finalArray = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Expected Output:
_finalArray = {
LED = (
{
rate = "25,000";
type = Sony;
},
{
rate = "25,000";
type = Samsung;
},
);
LCD = (
{
rate = "15,000";
type = Samsung;
},
{
rate = "15,000";
type = Sony;
},
{
rate = "15,000";
type = LG;
},
{
rate = "15,000";
type = Onida;
},
);
Thanks in advance...
Check for each key in newResultSet if it exists and merge or add the array.
NSMutableDictionary *finalDictionary = [prevResultSet mutableCopy];
[newResultSet enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSArray *array = finalDictionary[key];
if (array)
finalDictionary[key] = [array arrayByAddingObjectsFromArray:obj];
else
finalDictionary[key] = obj;
}];
Well, this is expected.
From the Documentation, addEntriesFromDictionary tells that:
If both dictionaries contain the same key, the receiving dictionary’s
previous value object for that key is sent a release message, and the
new value object takes its place.
You need to use setObject to add each object to the dictionary.YOu need to loop through the keys of one dictionary and add it to the final dictionary.
Even setObject tells the same:
The key for value. The key is copied (using copyWithZone:; keys must
conform to the NSCopying protocol). If aKey already exists in the
dictionary, anObject takes its place.
You cannot have two same keys in the dictionary. All keys in the dictionary are unique.
If you still want to have the same key-value in the dictionary, you must use a different key.
For example, you have two dictionaries with following values:
NSDictionary *dict1=#{#"hello":#"1",#"hello2" :#"2"};
NSDictionary *dict2=#{#"hello":#"1",#"hello2":#"2",#"hello3":#"1",#"hello6":#"2",#"hello4":#"1",#"hello5" :#"2"};
NSMutableDictionary *mutableDict=[NSMutableDictionary dictionaryWithDictionary:dict1];
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
[mutableDict setObject:dict2[key] forKey:[NSString stringWithFormat:#"Ext-%#",key]];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
and by the end of this loop, your new mutable dictionaries will have the follwoing key-values:
{
"Ext-hello" = 1;
"Ext-hello2" = 2;
hello = 1;
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
As you can see, hello, and hello2 keys are renamed as Ext-hello1, Ext-hello2. form the dict1, and you still have all the dict2 values added to your mutable dict.
IF you don't want to add a new key, then you can add the values into an arrya and add that array to the dictionary. YOu can modify the for-loop to:
for (id key in dict2.allKeys){
for (id subKey in dict1.allKeys){
if (key==subKey) {
NSMutableArray *myArr=[[NSMutableArray alloc]init];
[myArr addObject:dict1[subKey]];
[myArr addObject:dict2[key]];
[mutableDict setObject:myArr forKey:key];
}else{
[mutableDict setObject:dict2[key] forKey:key];
}
}
}
And now you will have the values merged into an array:
{
hello = (
1,
1
);
hello2 = 2;
hello3 = 1;
hello4 = 1;
hello5 = 2;
hello6 = 2;
}
In this way, the number of keys will be same, and the values for the same key will be added as an array.

Conditional Statement: separate custom objects with an object header in an array (Code example)

data (
{
"name" = "Conway";
"country" = "England";
},
{
"name" = "Bale";
"country" = "Wales";
},
{
"name" = "Stephens";
"country" = "Scotland";
},
{
"name" = "Michael";
"country" = "England";
},
{
"name" = "Pedro";
"country" = "Spain";
},
{
"name" = "Patrick";
"country" = "England";
},
{
"name" = "John";
"country" = "Ireland";
},
{
"name" = "Bob";
"country" = "Ireland";
}
)
I have a JSON array I am parsing. The goal is to display this content in a picker view. However the picker view is custom, the list will appear like this:
**Ireland**
John
Bob
**England**
Conway
Michael
Patrick
etc etc.
As you can see however, the JSON to be parsed is not organised nicely and separated by headers, so I have the joy of doing it in the app instead :( but I am up for the challenge.
I have a player object.
Player.h
NSString * name;
NSString * country;
BOOL isHeader;
The block of code is below that I use to loop through the contents of the downloaded JSON. My current implementation is not ideal, and a bit confusing. But I couldn't think of any other way, I am always open to solutions to do this a quicker way.
I loop through the contents, if its the first time the object is being done, then isHeader is set to true.
The final Array is to contain all the objects from the initial array, but categorised by the country they are from, the country header is also set as a Player object, but with isHeader true. I am open to alternative ways of doing this. The end goal for each object to be separated with a header. I would preferably like to use an array of objects as well, but open to better practice suggestions.
for (int i=0; i < mArray.count; i++) {
if (i==0) {
Player * pPlayer = mArray[i];
pPlayer.isHeader=YES;
[headerArray addObject:pPlayer];
[catArray addObject:pPlayer];
}
else{
BOOL newHeader=YES;
for (int j=0; j<headerArray.count; j++) {
Player * jPlayer =mArray[i];
Player * headerPlayer = headerArray[j];
if ([headerPlayer.country isEqualToString:jPlayer.country]) {
newHeader=NO;
jPlayer.isHeader=NO;
[catArray addObject:jPlayer];
}
}
if (newHeader==YES) {
Player * hPlayer = mArray[i];
hPlayer.isHeader=YES;
[headerArray addObject:hPlayer];
[catArray addObject:hPlayer];
}
}
}
for (int k=0; k<headerArray.count; k++) {
[finalArray addObject:headerArray[k]];
for (int y=0; y<catArray.count; y++) {
Player *cPlayer = catArray[y];
Player *hPlayer = headerArray[k];
if ([hPlayer.country isEqualToString:cPlayer.country]) {
[finalArray addObject:cPlayer];
}
}
}
The current result is:
**Ireland**
**Ireland**
Bob
**England**
**England**
Michael
Patrick
So something is definitely wrong with my conditional statement.
NSMutableDictionary *players = [NSMutableDictionary dictionary];
for(Player *player in mArray) {
NSString *country = player.country;
NSMutableArray *playersArray = players[country];
if(!playersArray) {
playersArray = [NSMutableArray array];
}
[playersArray addObject:player.name];
players[country] = playersArray;
}
I think this should do it, although I'll admit I haven't tested it.
As Droppy said, if you want the headers ordered you'll have to put them in an array. You can get the headers via [players allKeys]; and order them using sortUsingComparator: -- then traverse the players dictionary getting each key in turn from the sorted array.

I'm having trouble accessing the value I need from an NSDictionary object

I'm having trouble accessing the value I need in an NSDictionary object, a song has multiple values under the track key, but since dictionaries aren't indexable, I'm unable to access the values individually. I have tried storing the object for the track key as an array but the two entries become a single string entry and therefore the array is only of length 1 and not helpful.
Also, doing something like [response valueForKeyPath#"response.songs.tracks.foreign_id"] gives me both foreign ids, how can I just get the first one? I've been struggling with this for a while, have searched all around stackoverflow for answers but none have worked, any help is appreciated, thanks!
This is the data in the NSDictionary:
{
response = {
songs = (
{
"artist_foreign_ids" = (
{
catalog = spotify;
"foreign_id" = "spotify:artist:6vWDO969PvNqNYHIOW5v0m";
}
);
"artist_id" = AR65K7A1187FB4DAA4;
"artist_name" = "Beyonc\U00e9";
id = SOUTJIT142F256C3B5;
title = "Partition (Explicit Version)";
tracks = (
{
catalog = spotify;
"foreign_id" = "spotify:track:2vPTtiR7x7T6Lr17CE2FAE"; //I WANT TO ACCESS JUST THIS VALUE
"foreign_release_id" = "spotify:album:1hq4Vrcbua3DDBLhuWFEVQ";
id = TRLHJRD1460052F846;
},
{
catalog = spotify;
"foreign_id" = "spotify:track:6m4ZFQb3zPt3IdRDTN3tfb";
"foreign_release_id" = "spotify:album:5KPpho7rztJrZVA9yXjk8K";
id = TRYMBSK146005C3A46;
}
);
}
);
status = {
code = 0;
message = Success;
version = "4.2";
};
};
}
The tracks in your sample dictionary appear to already be an array (of dictionaries), so you should be able to do something like:
NSArray *songs = response[#"songs"];
for (NSDictionary *songDict in songs) {
NSArray *tracks = songDict[#"tracks"];
for (NSDictionary *trackDict in tracks) {
NSString *trackForeignId = trackDict[#"foreign_id"];
// Do whatever you like with trackForeignId here.
}
}

Extracting data from nested NSDictionary's in a json array

I have a json array that I'm trying to extract data from. The array was created using NSJSONSerialization. Here is what the json array looks like from NSLog([jsonArray debugDescription]);:
{
properties = (
{
ID = 12345;
PropertyName = "McDonalds";
key = 00112233445566778899aabbccddeeff;
},
{
ID = 12346;
PropertyName = "Taco Bell";
key = 00112233445566778899aabbccddeef0;
},
{
ID = 12347;
PropertyName = "Burger King";
key = 00112233445566778899aabbccddeef1;
}
);
success = 1;
totalCount = 3;
}
I need to extract each ID and each Property name and dump the values into separate arrays. How can I do this?
You can use Key-Value Coding:
NSArray *ids = [jsonArray valueForKeyPath:#"properties.ID"];
NSArray *propertyNames = [jsonArray valueForKeyPath:#"properties.PropertyName"];