Sorting array of multiple dictionaries - iphone

My array contains three dictionaries per object of the array.
{
avg = {
avg1 = 50;
avg2 = 60;
};
posts = {
alcoholContent = 450;
name = "BBB";
origin = United States;
};
reviews = {
rev1 = "Test review 1";
rev2 = "Test review 2";
};
}
{
avg = {
avg1 = 30;
avg2 = 20;
};
posts = {
alcoholContent = 550;
name = "AAA";
origin = United States;
};
reviews = {
rev1 = "Test review 1";
rev2 = "Test review 2";
};
}
I want to sort array acceding by key "name" (of post dictionary).
How can I do it?
I tried normal sorting methods using sort descriptors, but did not work

Try sortUsingComparator:
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary *dict1 = obj1;
NSDictionary *dict2 = obj2;
NSString *string1 = [[dict1 objectForKey:#"posts"] objectForKey:#"name"];
NSString *string2 = [[dict2 objectForKey:#"posts"] objectForKey:#"name"];
return [string1 compare:string2];
}];

Related

How to filter array of NSDictionary for key separated by comma

I have an array of NSDictionary.NSDictionary has a key named as multiple_image key that contain string separated by ,.
I want set of array that contain 123.png for multiple_images key.
Can some one show me how to do this using NSPredicate or without predicate.
//Array
{
Image = "<UIImage: 0xf72df30>";
active = yes;
"admin_id" = 169;
"category_id" = 32;
"chef_id" = 175;
descr = "Cool tea to cool down the mind.";
id = 110;
"multiple_images" = "Jellyfish.jpg,345.png";
name = "Southern Sweet Ice Tea";
price = 160;
rating = 3;
selected = 0;
"subcat_id" = 23;
"tag_id" = 45;
"tax_id" = 10;
"tax_value" = "12.00";
},
{
Image = "<UIImage: 0xf72ebd0>";
active = yes;
"admin_id" = 169;
"category_id" = 31;
"chef_id" = 175;
descr = "Ingredients are almonds or cashews. No hydrogenated stuff, no extra weirdo ingredients";
id = 107;
"multiple_images" = "Jellyfish.jpg,123.png";
name = "Butter Chicken";
price = 300;
rating = 3;
selected = 0;
"subcat_id" = 24;
"tag_id" = 43;
"tax_id" = 9;
"tax_value" = "0.00";
},
{
Image = "<UIImage: 0xf72f870>";
active = yes;
"admin_id" = 169;
"category_id" = 31;
"chef_id" = 173;
descr = "Raw vegetables including carrots, cucumbers.";
id = 100;
"multiple_images" = "Jellyfish.jpg,shake.png,";
name = Salads;
price = 50;
rating = 3;
selected = 0;
"subcat_id" = 22;
"tag_id" = 44;
"tax_id" = 9;
"tax_value" = "0.00";
}
Using predicates,
[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"multiple_images CONTAINS '123'"]];
Using predicates, but with blocks
NSArray *filtered = [test filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:
^BOOL(NSDictionary *evaluatedObject, NSDictionary * bindings) {
NSString *key = #"123";
return ([evaluatedObject[#"multiple_images"] rangeOfString:key].location != NSNotFound);
}]];
Try
NSDictionary *item = mainArray[0];
NSString *imagesString = item[#"multiple_images"];
NSArray *images = [imagesString componentsSeparatedByString:#","];
Now you can use the images
Try this code
for (int i=0; i<[mainArray count]; i++) {
NSDictionary *item = [mainArray objectAtIndex:i];
NSString *imagesString = item[#"multiple_images"];
NSArray *images = [imagesString componentsSeparatedByString:#","];
for (int j=0;j<[images count]; j++) {
if ([[images objectAtIndex:j] isEqualToString:#"123.png"]) {
///Your Required code;
}
}
}
So you want to save the dictionary that has 123.png.
maybe you can try something like this:
NSMutableArray *arr = [NSMutableArray new];// your array of objects(dictionaries)
__block NSMutableArray *images123 = [NSMutableArray new];
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSMutableDictionary *dictionary = (NSMutableDictionary *)obj;
if([[dictionary allKeys]containsObject:#"multiple_images"]){
NSString *imageList = (NSString *)[dictionary objectForKey:#"multiple_images"];
NSArray *arrayImages = [imageList componentsSeparatedByString:#","];
if([arrayImages containsObject:#"123.png"]){
[images123 addObject:dictionary];
}
}
}];

Merge two NSDIctionay in one NSDictonary

I want to merge two NSDictionary in one NSDictionary.
my first DIctionary
BreakFast Dates Dic {
"2012-07-24" = "27";
"2012-08-03" = "98";
"2012-08-06" = "4203";
"2012-08-23" = "0";
"2012-08-24" = "0";
"2012-09-11" = "36";
"2012-09-19" = "450";
"2012-09-24" = "36";
Goals = 3;
}
my second Dictonary
Dinner Dates Dic {
"2012-08-03" = "100";
"2012-08-27" = "0";
"2012-09-19" = "270";
Goals = 4;
}
i want to merge both dictionary into one. like if in breakfast i have "2012-09-19" and same date i have in dinner. i want to separate both values by comma (,) .
my resultant dictionary should be like this.
combine {
"2012-07-24" = "27,0";
"2012-08-03" = "98,100";
"2012-08-06" = "4203,0";
"2012-08-23" = "0,0";
"2012-08-24" = "0,0";
"2012-09-11" = "36,0";
"2012-09-19" = "450,270";
"2012-09-24" = "36,0";
Goals = 3,4;
}
NSMutableDictionary *combined = [objectDelegate.dataBreakFastSummary mutableCopy];
for(NSString *key in [combined allKeys])
{
NSString *breakfastDate = [objectDelegate.dataBreakFastSummary valueForKey:key];
NSString *dinnerDate = [objectDelegate.dataDinnerSummary objectForKey:key];
if(dinnerDate){
[combined setObject:[NSString stringWithFormat:#"%#,%#",breakfastDate, dinnerDate] forKey:key];
} else {
[combined setObject:[NSString stringWithFormat:#"%#,0",breakfastDate] forKey:key];
}
}
NSLog(#"Combine %#",combined);

Multidimensional array issues

I am creating a multidimensional array for sections / rows based on json data from our API. Looking at the logs the adding rows and sections look good but when I nslog the sections it only shows a bunch of the last object. It seems like the rows are not being added to sections.
What am I doing wrong to make the last API object show in the sections x times? x represents the json count. self.appointments is an NSArray *
According to objective-c multi-dimensional array it should work.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *sections = [[NSMutableArray alloc] init];
NSMutableArray *rows = [[NSMutableArray alloc] init];
NSString *lastDate = nil;
for (NSDictionary *dict in [json objectForKey:#"data"]) {
NSString *date = [dict objectForKey:#"date"];
NSLog(#"Dates: %# - %#", date, lastDate);
if (date != lastDate) {
if (lastDate == nil) {
NSLog(#"Adding Row 1");
[rows addObject:dict];
lastDate = date;
} else {
NSLog(#"Adding Section 1");
NSLog(#"Adding #rows %i",[rows count]);
[sections addObject:rows];
[rows removeAllObjects];
NSLog(#"Adding Row 2 %#",[dict objectForKey:#"start_time"]);
[rows addObject:dict];
lastDate = date;
}
} else {
NSLog(#"Adding Row 3");
[rows addObject:dict];
}
}
if (rows) {
NSLog(#"Adding Section 2");
NSLog(#"Adding #rows %i",[rows count]);
[sections addObject:rows];
}
NSLog(#"Sections: %#", sections);
self.appointments = [sections mutableCopy]; //I have also tried self.appointments = sections
sections = nil;
rows = nil;
Logs show
Sections: (
(
{
abbrev = "";
account = "";
"addOnService_id" = "";
alert = "";
"appt_id" = 1839384;
"appt_id_unique" = 1839384;
"appt_status_description" = "";
"appt_status_type" = "";
"c_id" = 47;
cost = "0.00";
"coupon_id" = "";
"creation_emp_id" = 2288;
"creation_timestamp" = 201111040717;
"customer_id" = 0;
"customer_notes" = "";
"customer_package_id" = "";
date = 20121228;
"employee_id" = 2288;
"employee_notes" = "";
employer = "";
"end_time" = 570;
"first_name" = "";
"history_id" = 1830959;
key = 134;
"last_emp_id" = 2288;
"last_name" = "";
"last_timestamp" = 201111040717;
"lead_description" = "";
"link_id" = 0;
"location_name" = "Telephonic Setup/Training";
"make_id" = "";
"middle_name" = "";
"model_id" = "";
"model_year" = "";
name = "My Name ";
odometer = "";
"other_vehicle" = "";
"package_name" = "";
"payment_type_description" = "";
"payment_type_id" = "";
"pet_id" = "";
"po_number" = "";
reason = "B.O.B";
"rebook_id" = "";
"recur_id" = 20954;
"rep_id" = "";
"room_id" = 0;
"room_name" = "";
service = "";
"service_id" = 0;
"service_time_description" = "";
spots = 1;
"staff_screen_name" = "John Smith";
"staff_type_id" = 0;
"start_time" = 540;
"status_id" = 0;
tip = "";
"type_id" = 8;
vin = "";
}
),
(
{
abbrev = "";
account = "";
"addOnService_id" = "";
alert = "";
"appt_id" = 1839384;
"appt_id_unique" = 1839384;
"appt_status_description" = "";
"appt_status_type" = "";
"c_id" = 47;
cost = "0.00";
"coupon_id" = "";
"creation_emp_id" = 2288;
"creation_timestamp" = 201111040717;
"customer_id" = 0;
"customer_notes" = "";
"customer_package_id" = "";
date = 20121228;
"employee_id" = 2288;
"employee_notes" = "";
employer = "";
"end_time" = 570;
"first_name" = "";
"history_id" = 1830959;
key = 134;
"last_emp_id" = 2288;
"last_name" = "";
"last_timestamp" = 201111040717;
"lead_description" = "";
"link_id" = 0;
"location_name" = "Telephonic Setup/Training";
"make_id" = "";
"middle_name" = "";
"model_id" = "";
"model_year" = "";
name = "My Name ";
odometer = "";
"other_vehicle" = "";
"package_name" = "";
"payment_type_description" = "";
"payment_type_id" = "";
"pet_id" = "";
"po_number" = "";
reason = "B.O.B";
"rebook_id" = "";
"recur_id" = 20954;
"rep_id" = "";
"room_id" = 0;
"room_name" = "";
service = "";
"service_id" = 0;
"service_time_description" = "";
spots = 1;
"staff_screen_name" = "John Smith";
"staff_type_id" = 0;
"start_time" = 540;
"status_id" = 0;
tip = "";
"type_id" = 8;
vin = "";
}
), ... over and over again.
With:
[sections addObject:rows];
[rows removeAllObjects];
[rows addObject:dict];
you keep adding the same rows object not a new one and keep changing the contents so the last contents display each time.
Try:
[sections addObject:[rows mutableCopy]];
[rows removeAllObjects];
[rows addObject:dict];
That way a new row is added each time.
Perhaps better yet:
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *sections = [NSMutableArray array];
NSMutableArray *rows = [NSMutableArray array];
NSString *lastDate = nil;
for (NSDictionary *dict in [json objectForKey:#"data"]) {
NSString *date = [dict objectForKey:#"date"];
if ([date isEqualToString:lastDate] == NO) {
if (lastDate == nil) {
[rows addObject:dict];
lastDate = date;
} else {
[sections addObject:rows];
rows = [NSMutableArray array];
[rows addObject:dict];
lastDate = date;
}
[rows addObject:dict];
}
}
if (rows) {
[sections addObject:rows];
}
self.appointments = sections;
Note that assigning 0 to an object does not release it, release does. But if you use convenience methods to create objects then they are autoreleased and no further action is necessary to release them.
Also note that when comparing strings one needs to use the isEqualToString: method to compare the contents, just using the = or != only compares the address of the strings.

sorting array of nested NSDictionary containing an array

Im quite new to iOS and objective.. heres my question..
if my array looks like this:
myArray = {
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "25236";
},
{
counter = "2";
close = "12458";
};
};
};
},
{
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "28556";
},
{
counter = "2";
close = "12118";
};
};
};
},
{
parentdict = {
childdict = {
aname = "Aname";
bname - "Bname";
cname = "Cname";
};
childarray = {
{
counter = "1";
close = "24356";
},
{
counter = "2";
close = "155628";
};
};
};
};
basically its an array of nested dictionary and inside one of the dictionary contains an array of dictionary (childarray) if i want to sort myArray by #"close" of array index 1, which is the one next to counter 2, exactly how should i do this?..(perhaps i should use NSSortDescriptor?)
thanks for the reply
You have presented your structure in the JSON format. I assume it is for sake of presenting it to the audience here. If you are actually starting with JSON string, you will have to convert it to nested NSArrayies and NSDictionaryies using some third-party libs or iOS 5 built-in classes..
Assuming you already have your top level NSArray* myArray, give it a try to the following code:
NSArray* myArray = // ... this is your array
NSArray* sorted_array = [myArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary* left = obj1;
NSDictionary* right = obj2;
NSDictionary* left_parent_dict = [left objectForKey: #"parentdict"];
NSDictionary* right_parent_dict = [right objectForKey: #"parentdict"];
NSArray* left_child_array = [left_parent_dict objectForKey: #"childarray"];
NSArray* right_child_array = [right_parent_dict objectForKey: #"childarray"];
NSDictionary* left_child_first = [left_child_array objectAtIndex: 1];
NSDictionary* right_child_first = [right_child_array objectAtIndex: 1];
NSString* left_close = [left_child_first objectForKey: #"close"];
NSString* right_close = [right_child_first objectForKey: #"close"];
NSNumber* left_val = [NSNumber numberWithInt: [left_close intValue]];
NSNumber* right_val = [NSNumber numberWithInt: [right_close intValue]];
return [left_val compare: right_val];
} ];
You will need, of course, to add some checks which I omitted for simplicity.
If you want to get descending order modify the last statement to:
return [right_val compare: left_val];
I would also suggest you considering SQL database for complex data structures as pointed out by Niko.
Sorting an array can be quite complex, especially when the array contains nested objects. May be you should create an SQLite database
You should use iOS 5.0's built in JSON API. [Here's a link to a great tutorial.] (http://www.raywenderlich.com/5492/working-with-json-in-ios-5). JSON is really easy to work with. And that site also has great tutorials on Core Data (iOS's SQLite API) here. There are two more parts to that tutorial as well.
Try this
[array sortUsingComparator:(NSComparator)^(id obj1, id obj2){
int firstValue = [[obj1 objectForKey:#"someKey"] intValue];
int secondValue = [[obj2 objectForKey:#"someKey"] intValue];
int valueDiff = firstValue - secondValue;
return (valueDiff == 0) ? NSOrderedSame : (valueDiff < 0) ? NSOrderedAscending : NSOrderedDescending;
}];

Trouble reading JSON object using Obj-C

I am trying to read the following json object using the json-framework and obj-C
{
Sections = {
Now = "Wednesday 9 February 2011 02:40";
Section = (
{
Article = (
{
Exceprt = "text here";
ID = 49011;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = False;
likesCounter = 0;
photoCounter = 0;
time = "21:12";
timeStamp = "2/8/2011 9:14:16 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
},
{
Exceprt = "text here";
ID = 49010;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = True;
likesCounter = 0;
photoCounter = 0;
time = "20:45";
timeStamp = "2/8/2011 9:10:59 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
},
{
Exceprt = "text here";
ID = 49008;
Title = "text here";
Type = Politics;
audioCounter = 0;
commentsCounter = 0;
hasMore = false;
important = False;
likesCounter = 0;
photoCounter = 0;
time = "20:28";
timeStamp = "2/8/2011 9:09:44 PM";
timeStatus = True;
videoCounter = 0;
viewsCounter = 0;
}
);
ID = 22;
Name = "EN Live";
totalNews = 3416;
}
);
};
}
My intent is to have a list of the articles (list of dictionaries) so that I can later access them easily. I have been stuck a while on this and my code is giving me an error about calling a non existent method for NSArray which has led me to suspect that I am misunderstanding the json object. I am totally new to this and any help is greatly appreciated.
Here's my code:
NSDictionary *results = [jsonString JSONValue];
NSDictionary *Articles = [[results objectForKey:#"Sections"] objectForKey:#"Section"];
NSArray *ListOfArticles = [Articles objectForKey:#"Article"];
for (NSDictionary *article in ListOfArticles)
{
NSString *title = [article objectForKey:#"Title"];
NSLog(title);
}
Thanks !
First of all, those aren’t valid JSON data. Names (in name/value pairs) are strings and must be quoted. String values must always be quoted. Boolean values must be either true or false (lowercase). Check http://json.org/ and http://www.ietf.org/rfc/rfc4627.txt?number=4627 and http://jsonlint.com
Here’s the structure of your data:
The top level value is an object (dictionary)
This object has a name (key) called Sections whose value is itself another object (dictionary)
Sections has a name (key) called Section whose value is an array
Each element in the Section array is an object (dictionary)
Each element in the Section array has a name (key) called Article whose value is an array, as well as other names (keys): ID, title, totalNews
Each element in the Article array is an object
If your JSON data were valid, you could parse them as follows:
// 1.
NSDictionary *results = [jsonString JSONValue];
// 2.
NSDictionary *sections = [results objectForKey:#"Sections"];
// 3.
NSArray *sectionsArray = [sections objectForKey:#"Section"];
// 4.
for (NSDictionary *section in sectionsArray) {
// 5.
NSLog(#"Section ID = %#", [section objectForKey:#"ID"];
NSLog(#"Section Title = %#", [section objectForKey:#"Title"];
NSArray *articles = [section objectForKey:#"Article"];
// 6.
for (NSDictionary *article in articles) {
NSLog(#"Article ID = %#", [article objectForKey:#"ID"];
NSLog(#"Article Title = %#", [article objectForKey:#"Title"];
// …
}
}
Your JSON framework is probably parsing out an NSDictionary where you're expecting an NSArray. It'll let you assign an NSDictionary to an NSArray, but then you'll get a runtime exception when you attempt to call a method on your "array". Judging by the JSON you posted (which isn't correct JSON), this is what I would have my parsing code look like. The names of the NSDictionaries and NSArrays are simply named after the JSON attributes they represent.
NSDictionary* results = [jsonString JSONValue];
NSDictionary* sections = [results valueForKey:#"Sections"];
NSArray* section = [sections valueForKey:#"Section"];
NSArray article = [[section objectAtIndex:0] valueForKey:#"Article"];
for (NSDictionary* anArticle in article) {
NSLog(#"%#", [anArticle valueForKey:#"Title"]);
}