Sort/group NSDictionary by key - iphone

i have data in NSDictionary like below :
Value : Football, Key: SPORT
Value : Cricket, Key: SPORT
Value : Fastrack, Key: PRODUCT/SERVICE
Value : Audi USA, Key: CARS
Value : BMW, Key: CARS
Value : Facebook, Key: PRODUCT/SERVICE
Value : TED, Key: WEBSITE
Value : National Geographic, Key: MEDIA/NEWS/PUBLISHING
Value : MyWebProduct, Key: WEBSITE
i want grouping of values according to key. what i need to do in this case or another suitable idea to implement this. I want result to be display something like :
SPORT : Football, Cricket
CARS : Audi, BMW
...
any help appreciable ...

Since you have multiple objects grouped under the same key, a dictionary of arrays would be a suitable structure to contain your data.
NSMutableDictionary *dict = [ [ NSMutableDictionary alloc ] init ];
NSArray *myItems = [ [ NSArray alloc ] initWithObjects:#"item one", #"item two", nil ];
[ dict setObject:myItems forKey:#"group of items" ];
Then you can access the group using
[dict objectForKey:#"group of items"]

Would this work for you, as a category on NSMutableDictionary:
- (void)setObject:(id)object inArrayForKey:(id <NSCopying>)key
{
id current = [self objectForKey:key];
if (!current || ![current isKindOfClass:[NSArray class]]) {
[self setObject:#[object] forKey:key];
} else {
[self setObject:[(NSArray *)current arrayByAddingObject:object] forKey:key];
}
}
Basically, you would then have a clean interface adding an item into an array associated with the key. You could choose to only make it an array if there was more than one item, if that's your preference.
If you're not familiar with adding categories, they allow you to add methods to existing classes. In Xcode just do new file > objective-C category and add the category on NSMutableDictionary.

NSDictionary cannot be sorted by default. If you want sorted dictionary, go on and implement your own subclass of it (this is one of the few valid reasons for which you can subclass a standard container object).

Related

Parsing JSON: brackets in response

I want to parse this JSON YouTube recently featured.
This is how I get the title of the videos:
NSString *response = [request responseString];
responseDict = [response JSONValue];
videoTitleArray = [responseDict valueForKeyPath:#"feed.entry.title.$t"];
And it works like I want it.
But I also want to display the author of the video.
But the following code for this does not work properly:
videoAuthorArray = [responseDict valueForKeyPath:#"feed.entry.author.name.$t"];
NSLog(#"%#", videoAuthorArray);
The list of the authors I get looks like this:
(
author 1
),
(
author 2
),
(
author 3
),
(
author 4
),
I can't display the names in for example a table view because of the brackets.
How can I display the author names like the video titles?
When you see an Author you see this:
"author":[{"name":{"$t":"mls"},"uri":{"$t":"http://gdata.youtube.com/feeds/api/users/mls"},"yt$userId":{"$t":"SZbXT5TLLW_i-5W8FZpFsg"}}]
this means: author is an array of author objects
each author object has: name object, a uri object and a yt$userId object
each of this objects described above is a NSDictionary
formated we have:
"author":[
{
"name": {
"$t":"mls"
},
"uri": {
"$t":"http://gdata.youtube.com/feeds/api/users/mls"
},
"yt$userId":{
"$t":"SZbXT5TLLW_i-5W8FZpFsg"
}
}
],
so if you have your videoAuthorArray each element is an NSDictionary and has this keys: name, uri and yt$userId
each of this objects has an NSDictionary with a single key: $t witch has the value

RestKit Object Mapping - One Entity, two mappings

After my last question was solved the JSON I'm receiving from the server changed to the following and I'm stuck handling the mapping to save the data with Core Data.
Entity
Key
- alias
- key
- keyType
- keyword
- unid
- until
JSON (from Server)
{
"documents": 1026,
"configuration":
{
...
},
"data":
[
{
"alias": "",
"key": "SALUTATION",
"keyType": "S",
"keyword": "Mr",
"unid": ""
},
...
{
"alias": "Automobile",
"key": "ACCOUNT_MARKET_SEGMENT",
"keyType": "A",
"keyword": "Automobile",
"unid": ""
}
],
"documentsFound": 770,
"maxCount": -1,
"since": "20120326200001",
"until": "20120326211309"
}
Now I want to map all the data from "data" plus the key "until" for the entity "Key" but can't find the right solution. My mapping so far to get the data looks like this and works well but misses the "until"-key, of course.
RKManagedObjectMapping* keyMapping = [RKManagedObjectMapping mappingForClass:[Key class]];
keyMapping.rootKeyPath = #"data";
[keyMapping mapKeyPath:#"key" toAttribute:#"key"];
[keyMapping mapKeyPath:#"keyword" toAttribute:#"keywordEN"];
[keyMapping mapKeyPath:#"alias" toAttribute:#"alias"];
keyMapping.setDefaultValueForMissingAttributes = YES;
Thanks for your ideas!
You are probably going to want to do two mappings. The first mapping will enclose the entire object and will have a relationship to the nested 'data' path.
RKObjectMapping *keyMapping = [RKObjectMapping mappingForClass:[Key class]];
[keyMapping mapAttributes:#"alias", #"key", nil];
[keyMapping mapKeyPath:#"keyword" toAttribute:#"keywordEN"];
RKObjectMapping *outerMapping = [RKObjectMapping mappingForClass:[Container class]];
[outerMapping mapKeyPath:#"data" toRelationship:#"keys" withMapping:keyMapping];
[outerMapping mapAttributes:#"since", #"until", "maxCount", "documentsFound", nil];
That will give you a new object with your metadata and then an array of the key objects on the keys attribute of your container. Rather than using the rootKeyPath, you can use the resourcePath based mapping registration on the 0.9.4 development branch (about to be released).

Reading a JSON string

I have a JSON String, in the format;
{
"name": "Alex",
"age": "12"
}
I know how to extract values from the above JSON. but at times, when there are no records in the database. i get a null value printed. (i undestand that this is not a valid JSON)
This null gets caught in the following if-condition.
SBJsonParser *parser = [SBJsonParser new];
NSDictionary *content = [pobjectWithString:[request responseString]];
if(!content){
NSLog(#" when its null it comes to this block");
return;
}
I need to read this value null and save it in a NSString. How can i do this ?
note: i have made use of ASIHTTPRequest to write the above code.
It's not clear what you're asking for. I think you want to detect when a null occurs (which you already seem to do with if(!content) ), then you want to create a string that either is empty, or has the word "null" in it. Why not:
if(!content) {
return #"null";
}
Of course, you could return whatever you wanted in the string.

How to read dictionary with child

Help me in reading this dictionary: (its an NSDictionary generated from XMLData)
Menus = {
Table1 = {
Phone = {
text = "\n (404) 371-1466";
};
text = "\n ";
};
text = "\n";
};
}
This should get you the phone number, for example:
NSString *phoneNum = [[[[dict objectForKey:#"Menus"] objectForKey:#"Table1"]
objectForKey:#"Phone"] objectForKey:#"text"];
You have one item in the dictionary - "Menus".
That single item is a dictionary, with two items - "Table 1" and "text". "Table 1" is a dictionary, "text" is an NSString.
Inside "Table 1", you have two items - "Phone" and "text". At this point, I think you can see the pattern...

How can I reference an Object and edit it's properties from a NSMutableArray?

NSMutableArray *persons = [ [ NSMutableArray alloc ] init ];
How can I edit person attributes without doing something like:
Person *p = [ [ Person alloc ] init ];
p = [ persons objectAtIndex:0 ];
p.name = "James Foo";
[ persons replaceObjectAtIndex: ([ persons count ] - 1 ) withObject:p];
I would like to do something like:
[ persons objectAtIndex:0 ].name = "James Foo";
But you can. You have to cast the generic id into your type though:
((Person*)[persons objectAtIndex:0]).name = "James Foo";
This example code also has a memory leak; you shouldn't need to alloc a new person instance in that case; you could just do the following if you don't want to cast anything:
Person *p = [persons objectAtIndex:0];
p.name = #"James Foo";
and you don't need to re-add it to the array since getting the object at a location doesn't remove it from the array on its own.