UITableview with multiple rows and sections - ios

I have timeSlotArr which contains data in the form of given.
timeSlotArr ++++++++ (
{
availablenow = 0;
callbackSlotId = "96a8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "07:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T01:30:00Z";
day = Wednesday;
},
{
availablenow = 0;
callbackSlotId = "9aa8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "09:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T03:30:00Z";
day = Wednesday;
},
{
availablenow = 0;
callbackSlotId = "9ca8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "10:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T04:30:00Z";
day = Wednesday;
}
)
I want to display my data in UITableView multiple sections and multiple rows inside it.
no of sections are decided based on "day" key(sections is array) and elementsInSection are the data inside sections
for (NSDictionary *dict in timeSlotArr) {
NSString *day = [dict objectForKey:#"day"];
if (![sections containsObject:day]) {
[sections addObject:day];
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:dict];
[elementsInSection addObject:arr];
} else {
NSMutableArray *arr = [elementsInSection objectAtIndex:[sections indexOfObject:day]];
[arr addObject:dict];
[elementsInSection setObject:arr atIndexedSubscript:[sections indexOfObject:day]];
}
}
NSLog(#"elementsInSection ++++++++ %#",elementsInSection);
elementsInSection Returns 1 instead of 3 here is wrong... 3 means data of `timeSlotArr` with key `day`
NSLog(#"sections ++++++++ %#",sections); //Returns 1 which is right

As per my experience you can achieve above sections and row structure in your table view by filtering your data like below:
Step 1: What you need in sections is Day.
so we will get all unique days from your array.
NSArray *uniqueDays = [arrayData valueForKeyPath:#"#distinctUnionOfObjects.day"];
Unique Days Result :
(
Wednesday,
Monday,
Tuesday
)
Step 2: Now we need day wise array contains only that day data array:
NSMutableDictionary *dictData1 = [NSMutableDictionary dictionary];
for (NSString *strDay in uniqueDays) {
NSArray *filteredDay = [arrayData filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(day == %#)", strDay]];
[dictData1 setObject:filteredDay forKey:strDay];
}
Filtered Data Result :
{
Monday = (
{
availablenow = 0;
callbackSlotId = "9ca8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "10:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T04:30:00Z";
day = Monday;
},
{
availablenow = 0;
callbackSlotId = "9ca8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "10:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T04:30:00Z";
day = Monday;
}
);
Tuesday = (
{
availablenow = 0;
callbackSlotId = "9ca8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "10:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T04:30:00Z";
day = Tuesday;
}
);
Wednesday = (
{
availablenow = 0;
callbackSlotId = "96a8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "07:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T01:30:00Z";
day = Wednesday;
},
{
availablenow = 0;
callbackSlotId = "9aa8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "09:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T03:30:00Z";
day = Wednesday;
},
{
availablenow = 0;
callbackSlotId = "9ca8a387-a2a1-e611-8101-000c29821561";
callbackSlotName = "10:00 AM";
date = "2016-12-21";
dateInUtc = "2016-12-21T04:30:00Z";
day = Wednesday;
}
);
}
Now you can use Unique Days as section array.
And dictData dictionary as row array and fetch data based on section.
Edit : now use above filter array in table view methods
#pragma mark --- UITableView DataSource methods
//Section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return uniqueDays.count;
}
//Row
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[dictData1 objectForKey:uniqueDays[section]] count];
}
//Cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *aCell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSArray *arrDayData = [dictData1 objectForKey:uniqueDays [indexPath.section]];
NSDictionary *dictDetail = arrDayData[indexPath.row];
aCell.textLabel.text = dictDetail[#"callbackSlotId"];
return aCell;
}
Let me know if you required any thing else.

Related

Unable to get all Matching string from NSDictionary iOS

I am new to iOS and little weak in logic.
Can any one help me here,
I want to get all matching data from NSDictionary.
eg:
my tempDict is NSDictionary which contains this,
tempDict:
errorCode = 00;
errorMessage = "<null>";
pastConsultations = (
{
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = q;
today = Yes;
},
{
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = g;
today = Yes;
},
{
date = "13 December 2016";
day = Tuesday;
doctorName = "<null>";
localTime = "12:30 PM";
symptoms = fever;
today = No;
}
);
upcomingConsultations = (
{
date = "16 December 2016";
day = Friday;
localTime = "09:30 PM";
symptoms = "";
today = Yes;
},
{
date = "16 December 2016";
day = Friday;
localTime = "09:30 PM";
symptoms = chj;
today = Yes;
},
{
date = "18 December 2016";
day = Sunday;
localTime = "12:30 PM";
symptoms = "test an incoming ";
today = No;
}
);
}
Inside a pastConsultations key i want to get all nested data which contains AM
i.e my output should be:
{ //Array at 0th index
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = q;
today = Yes;
},
{ //Array at 1st index
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = g;
today = Yes;
}
}
Here is the code i have tried but it is not working, please help where i am making mistake?
NSArray *allKeys;
for (int i=0; i<[tempDict count]; i++) {
allKeys = [[[tempDict valueForKey:#"upcomingConsultations"] objectAtIndex:i] allKeys];
NSString *targetKey = nil;
// NSArray *allKeys = [[tempDict valueForKeyPath:#"pastConsultations"] allKeys];
for (int j = 0; j < [allKeys count]; ++j) {
NSString *key = [allKeys objectAtIndex:i];
NSString *obj = [[[tempDict valueForKey:#"upcomingConsultations"] objectAtIndex:i] objectForKey:key];
if ([obj rangeOfString:searchText].location != NSNotFound) { // searchedString is what you're looking for
targetKey = key;
NSLog(#"found match");
break;
}
}
}
Try this code:
assuming you already have tempDict dictionary loaded.
NSMutableArray *morningPastArr = [[NSMutableArray alloc] init];
NSArray *pastArray = [tempDict objectForKey:#"pastConsultations"];
for (int i=0;i<[pastArray count]; i++) {
NSDictionary *eachPast = [pastArray objectAtIndex:i];
NSString *time = [eachPast objectForKey:#"localTime"];
if (![time rangeOfString:#"AM"].location == NSNotFound) {
[morningPastArr addObject:eachPast];
}
}
// finally you will have like what you need in morningPastArr.
EDIT:
If you want to combine search results, for example, results for AM entry and Friday only you can do like this:
NSMutableArray *morningAndFridayPastArr = [[NSMutableArray alloc] init];
NSArray *pastArray = [tempDict objectForKey:#"pastConsultations"];
for (int i=0;i<[pastArray count]; i++) {
NSDictionary *eachPast = [pastArray objectAtIndex:i];
NSString *time = [eachPast objectForKey:#"localTime"];
NSString *day = [eachPast objectForKey:#"day"];
if ((![time rangeOfString:#"AM"].location == NSNotFound)&&([day isEqualToString:#"Friday"])) {
[morningAndFridayPastArr addObject:eachPast];
}
}
You can use NSPredicate for that as follows:
NSPredicate *predicate;
NSMutableArray *filteredData=[[NSMutableArray alloc]init];
predicate = [NSPredicate predicateWithFormat:#"localTime contains[c] %#",#"AM"];
//OR Use below predicate as suggested by Rishi
predicate = [NSPredicate predicateWithFormat:#"localTime ENDSWITH 'AM'"];
filteredData=[[[tempDict valueForKey:#"pastConsultations"] filteredArrayUsingPredicate:predicate]] mutableCopy];
Hope this will help.

Nesting NSDictionary based on value

i've data from Library that return this:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:distanceNumber,#"distance",idChallengerN,#"idChallenger",dateFrom, #"date", nil];
[_array addObject:dict];
If i print _array this is there result:
{
date = "2015-07-31 14:50:40 +0000";
distance = "-1";
idChallenger = 43;
},
{
date = "2015-07-31 16:18:57 +0000";
distance = "-1";
idChallenger = "-1";
},
{
date = "2015-07-31 16:19:05 +0000";
distance = "-1";
idChallenger = "-1";
},
and it's ok, now I should get each date and group this _array based on weeks...
I've tried:
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSWeekOfYearCalendarUnit fromDate:date];
NSLog(#"date week = %ld",(long)[dateComponents weekOfYear]);
NSNumber *weekN = [NSNumber numberWithInteger:[dateComponents weekOfYear]];
if ([tempDic objectForKey:weekN]) {
//contains
}
else{
//not contains
}
weekN return the number of the week in year based on 'date',
now i'm stuck to how group certain data if have the same number of week, like this for example:
weekN = 31 {
{
idChallenger = 43;
idChallenger = 22;
}
}
weekN = 32 {
{
idChallenger = 55;
idChallenger = 21;
idChallenger = 678;
}
}
thanks to popctrl :
NSMutableArray *weekArray = [NSMutableArray array];
for(int i = 0; i < 52; i++){
[weekArray addObject:[NSMutableArray array]];
}
//This replaces your for loop
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
//Notice that I changed NSWeekOfYearCalendarUnit to NSCalendarUnitWeekOfYear, as NSWeekOfYearCalendarUnit has been deprecated
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekOfYear fromDate:date];
NSMutableArray *innerArray = weekArray[[dateComponents weekOfYear] - 1];
[innerArray addObject:dict];
}
this code produce very well structure, but if I want divide weeks in year before?
If you're looking for something that follows the example you've given at the bottom of your post, that would be an array of arrays, where the first array is indexed by date and the inner arrays have no specific order.
If you would like to preserve the initial dictionary data structure, just make the values contained in that array of arrays the dictionary.
EDIT: Here's the code I would use
//To initialize the array
NSMutableArray *weekArray = [NSMutableArray array];
for(int i = 0; i < 52; i++){
[weekArray addObject:[NSMutableArray array]];
}
//This replaces your for loop
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
//Notice that I changed NSWeekOfYearCalendarUnit to NSCalendarUnitWeekOfYear, as NSWeekOfYearCalendarUnit has been deprecated
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekOfYear fromDate:date];
NSMutableArray *innerArray = weekArray[[dateComponents weekOfYear] - 1];
[innerArray addObject:dict];
}

Sort Descriptor not working in ios

i used the Sort Descriptor to Sort the NSMutableArray By one & multiple Values,First i tried by to sort By Price,it sort in some other Order here is my code help me,
My
i create the Dictionary by below code and added to the NSMutableArray
for(int i=0;i<[priceArray count];i++)
{
cellDict=[[NSMutableDictionary alloc]init];
[cellDict setObject:nameArray[i] forKey:#"Name"];
[cellDict setObject:splPriceArray[i] forKey:#"Percentage"];
[cellDict setObject:priceArray[i] forKey:#"Price"];
[resultArray addObject:cellDict];
}
// To Sort in Ascending Order
NSSortDescriptor *sort =[[NSSortDescriptor alloc] initWithKey:#"Price" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObjects:sort, nil];
NSArray *sortedArray=[resultArray sortedArrayUsingDescriptors:descriptors];
NSLog(#"Result %# Sorted arr %#",resultArray, sortedArray);
And Output is:
Result (
{
Name = "Black Eyed Peas";
Percentage = 0;
Price = 80;
},
{
Name = "Black Gram";
Percentage = 0;
Price = 56;
},
{
Name = "Channa White";
Percentage = 0;
Price = 100;
},
{
Name = "Double Beans";
Percentage = 0;
Price = 95;
},
{
Name = "Gram Dall";
Percentage = 0;
Price = 100;
},
{
Name = "Green Moong Dal";
Percentage = 0;
Price = 150;
},
{
Name = "Ground Nut";
Percentage = 0;
Price = 140;
},
{
Name = "Moong Dal";
Percentage = 0;
Price = 75;
},
{
Name = "Orid Dal";
Percentage = 0;
Price = 100;
},
{
Name = "Toor Dal";
Percentage = 0;
Price = 150;
}
) Sorted arr (
{
Name = "Channa White";
Percentage = 0;
Price = 100;
},
{
Name = "Gram Dall";
Percentage = 0;
Price = 100;
},
{
Name = "Orid Dal";
Percentage = 0;
Price = 100;
},
{
Name = "Ground Nut";
Percentage = 0;
Price = 140;
},
{
Name = "Green Moong Dal";
Percentage = 0;
Price = 150;
},
{
Name = "Toor Dal";
Percentage = 0;
Price = 150;
},
{
Name = "Black Gram";
Percentage = 0;
Price = 56;
},
{
Name = "Moong Dal";
Percentage = 0;
Price = 75;
},
{
Name = "Black Eyed Peas";
Percentage = 0;
Price = 80;
},
{
Name = "Double Beans";
Percentage = 0;
Price = 95;
}
)
Here The Sorted Array Sorting in some other Order I want to sort this in Ascending order by price.
It's unclear what your test data looks like - but the following snippet works as expected
NSArray *priceArray = [NSArray arrayWithObjects:#(74),#(100),#(100),#(130), nil];
NSArray *nameArray = [NSArray arrayWithObjects:#"Yva",#"Hallo", #"Adam", #"Xavier", nil];
NSMutableArray *resultArray = [NSMutableArray new];
for(int i=0;i<[priceArray count];i++)
{
NSMutableDictionary *cellDict=[[NSMutableDictionary alloc]init];
[cellDict setObject:nameArray[i] forKey:#"Name"];
[cellDict setObject:priceArray[i] forKey:#"Percentage"];
[cellDict setObject:priceArray[i] forKey:#"Price"];
[resultArray addObject:cellDict];
}
// Sort by Name
//NSSortDescriptor *sort =[[NSSortDescriptor alloc] initWithKey:#"Price" ascending:YES];
// Sort by Name
NSSortDescriptor *sort =[[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:sort, nil];
NSArray *sortedArray=[resultArray sortedArrayUsingDescriptors:descriptors];
NSLog(#"Result %# Sorted arr %#",resultArray, sortedArray);
Result:
2015-07-11 12:54:54.358 ret[10480:162783] Result (
{
Name = Yva;
Percentage = 74;
Price = 74;
},
{
Name = Hallo;
Percentage = 100;
Price = 100;
},
{
Name = Adam;
Percentage = 100;
Price = 100;
},
{
Name = Xavier;
Percentage = 130;
Price = 130;
}
) Sorted arr (
{
Name = Adam;
Percentage = 100;
Price = 100;
},
{
Name = Hallo;
Percentage = 100;
Price = 100;
},
{
Name = Xavier;
Percentage = 130;
Price = 130;
},
{
Name = Yva;
Percentage = 74;
Price = 74;
}
)

How to make UITableView Sections on Yearly basis and Populate data monthly basis in rows of each section

I have the following array of data which I am fetching from SQLite3 database.
array (
{
amount = "$100";
balance = "$1505";
date = "06/22/2015";
id = 16;
note = Pay;
type = Pay;
},
{
amount = "$1000";
balance = "$1405";
date = "06/22/2015";
id = 15;
note = Pay;
type = Pay;
},
{
amount = "$200";
balance = "$405";
date = "06/22/2015";
id = 14;
note = Pay;
type = Pay;
},
{
amount = "$100";
balance = "$205";
date = "06/22/2015";
id = 13;
note = Pay;
type = Pay;
},
{
amount = "$100";
balance = "$105";
date = "06/22/2015";
id = 12;
note = Pay;
type = Pay;
},
{
amount = "$50";
balance = "$5,320.00";
date = "06/16/2015";
id = 11;
note = Pay;
type = Pay;
},
{
amount = "$50";
balance = "$5,270.00";
date = "06/09/2015";
id = 10;
note = Pay;
type = Pay;
},
{
amount = "$50";
balance = "$5220";
date = "06/02/2015";
id = 9;
note = Pay;
type = Pay;
},
{
amount = "$100";
balance = "$5170";
date = "06/03/2015";
id = 8;
note = Pay;
type = Pay;
},
{
amount = "$100";
balance = "$5070";
date = "06/02/2015";
id = 7;
note = Pay;
type = Pay;
},
{
amount = "$20";
balance = "$4970";
date = "05/29/2015";
id = 6;
note = water;
type = Deposit;
},
{
amount = "$100";
balance = "$4950";
date = "05/29/2015";
id = 5;
note = water;
type = Expense;
},
{
amount = "$50";
balance = "$5050";
date = "05/29/2015";
id = 4;
note = Pay;
type = Pay;
}
)
I want to make a tableview with sections on yearly basis and in rows each section data will show monthly basis after performing calculation of income and expense. For more info I am attaching a screen shot herewith.
I am attempting to solve the problem using the following method.
-(NSMutableArray*)arrangeSection:(NSMutableArray *)source
{
NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
[_formatter setLocale:[NSLocale currentLocale]];
[_formatter setDateFormat:#"YYYY"];
NSMutableArray *arrayMain=[NSMutableArray array];
for (int i=0; i<source.count; i++){
NSDictionary *dict=source[i];
NSDateFormatter *_formatterLocal=[[NSDateFormatter alloc]init];
[_formatterLocal setLocale:[NSLocale currentLocale]];
[_formatterLocal setDateFormat:#"MM/dd/yyyy"];
NSDate * date = [_formatterLocal dateFromString:[dict objectForKey:TABLE_DATE]];
NSString *yy=[_formatter stringFromDate:date];
NSMutableDictionary *secDict=[NSMutableDictionary dictionary];
NSMutableArray *secArray=[NSMutableArray array];
if (i==0){
[secDict setObject:yy forKey:#"Year"];
[secArray addObject:dict];
[secDict setObject:secArray forKey:#"Data"];
[arrayMain addObject:secDict];
}
else{
BOOL flg=NO;
for (NSDictionary *dict2 in arrayMain){
if([[dict2 objectForKey:#"Year"]isEqualToString:yy]){
flg=YES;
[[dict2 objectForKey:#"Data"]addObject:dict];
break;
}
}
if (!flg){
[secDict setObject:yy forKey:#"Year"];
[secArray addObject:dict];
[secDict setObject:secArray forKey:#"Data"];
[arrayMain addObject:secDict];
}
}
}
return arrayMain;
}
If I understand you requirement correct you want a section per year, each section with 12 rows, one per month.
This should not be too hard to achieve :).
I suggest that you make models of your JSON object:
{
amount = "$20";
balance = "$4970";
date = "05/29/2015";
id = 6;
note = water;
type = Deposit;
}
Let's call this class a "MonthModel", then create a "YearModel" holding 12 (or less, if no data is available for said year) "MonthModels". I am posting a suggestion for a structure of models in the untested code below.
Something like:
YearModel
#interface YearModel()
#property (strong, nonatomic) NSArray *monthModels;
#property (strong, assign) NSInteger year;
#end
#implementation YearModel
- (instancetype)initModelForYear:(NSInteger)year withMonthModels:(NSArray*)monthModels {
self = [super init];
if(self) {
self.year = year;
self.monthModels = monthModels;
}
return self;
}
#end
Your MonthModel
#interface MonthModel()
#property (strong, assign) NSFloat balance;
#property (strong, assign) NSFloat amount;
#end
#implementation MonthModel
- (instancetype)initWithBalance:(NSFloat)balance andAmount:(NSFloat)amount {
self = [super init];
if(self) {
self.balance = balance;
self.amount = amount;
}
return self;
}
#end
If your UIViewController is your UITableViewDataSource, then it can use an array of YearModels
#interface MyViewController() <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSArray* yearModels;
#end
#implementation MyViewController
- (MonthModel*)monthModelForIndexPath:(NSIndexPath*)indexPath {
YearModel* yearModel = [yearModels objectAtIndex:indexPath.section];
MonthModel* monthModel = [yearModel.monthModels objectAtIndex:indexPath.row];
return monthModel;
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [yearModels count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
YearModel* yearModel = [yearModels objectAtIndex:section];
return [yearModel.monthModels count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"MonthCell";
MonthCell *cell = (MonthCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
MonthModel* monthModel = [self monthModelForIndexPath:indexPath];
[cell updateWithModel:monthModel];
return cell;
}
#end
Hopefully it will not be that tricky for you to somewhere in code create a method which reads your data from the SQLite and creates those models suggested above. And then set the "yearModels" property in the UIViewController.
However, please let me know if you need some inspiration the SQLite -> Model conversion.
Good luck!
I have solved my problem by the following method of sorting.
-(NSMutableArray*)arrangeSection:(NSMutableArray *)source
{
NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
[_formatter setLocale:[NSLocale currentLocale]];
[_formatter setDateFormat:#"YYYY"];
NSString *year = #"";
NSString *month = #"";
NSMutableArray *arrayMain=[[NSMutableArray alloc] init];
NSMutableDictionary *lastDict = [[NSMutableDictionary alloc] init];
NSMutableArray *lastArray = [[NSMutableArray alloc] init];
for (int i=0; i<source.count; i++){
NSDictionary *dict=source[i]; // Year data dictionary
NSDateFormatter *_formatterLocal=[[NSDateFormatter alloc]init];
[_formatterLocal setLocale:[NSLocale currentLocale]];
[_formatterLocal setDateFormat:#"MM/dd/yyyy"];
NSDate * date = [_formatterLocal dateFromString:[dict objectForKey:TABLE_DATE]];
[_formatter setDateFormat:#"YYYY"];
NSString *currentYear=[_formatter stringFromDate:date];
if (![year isEqualToString:currentYear]) {
if (i!=0) {
[lastDict setObject:year forKey:#"Year"];
[lastDict setObject:arrayMain forKey:#"Data"];
[lastArray addObject:lastDict];
lastDict = [[NSMutableDictionary alloc] init];
arrayMain=[[NSMutableArray alloc] init];
}
}
[_formatter setDateFormat:#"MMMM"];
NSString *currentMonth = [_formatter stringFromDate:date];
if (![month isEqualToString:currentMonth]) {
NSMutableDictionary *secDict=[[NSMutableDictionary alloc] init];
[secDict setObject:currentMonth forKey:TABLE_DATE];
if ([[dict valueForKey:TABLE_TYPE] isEqualToString:#"Expense"]) {
[secDict setObject:[dict valueForKey:TABLE_AMOUNT] forKey:TABLE_AMOUNT];
}
else
{
[secDict setObject:#"0" forKey:TABLE_AMOUNT];
}
if ([[dict valueForKey:TABLE_TYPE] isEqualToString:#"Deposit"])
{
[secDict setObject:[dict valueForKey:TABLE_AMOUNT] forKey:TABLE_NOTE];
}
else
{
[secDict setObject:#"0" forKey:TABLE_NOTE];
}
[secDict setObject:[dict valueForKey:TABLE_BALANCE] forKey:TABLE_BALANCE];
[arrayMain addObject:secDict];
}
else
{
NSMutableDictionary *previousOBJ= [arrayMain objectAtIndex:[arrayMain count]-1];
if ([[dict valueForKey:TABLE_TYPE] isEqualToString:#"Expense"])
{
[previousOBJ setValue:[NSString stringWithFormat:#"%d", [[previousOBJ valueForKey:TABLE_AMOUNT] integerValue] + [[dict valueForKey:TABLE_AMOUNT] integerValue]] forKey:TABLE_AMOUNT];
}
if ([[dict valueForKey:TABLE_TYPE] isEqualToString:#"Deposit"])
{
[previousOBJ setValue:[NSString stringWithFormat:#"%d", [[previousOBJ valueForKey:TABLE_NOTE] integerValue] + [[dict valueForKey:TABLE_AMOUNT] integerValue]] forKey:TABLE_NOTE];
}
[arrayMain replaceObjectAtIndex:[arrayMain count]-1 withObject:previousOBJ];
}
month = currentMonth;
year = currentYear;
if (i==source.count-1) {
[lastDict setObject:year forKey:#"Year"];
[lastDict setObject:arrayMain forKey:#"Data"];
[lastArray addObject:lastDict];
}
}
return lastArray;
}

NSArray of NSDictionaries - merge dictionaries with same key value pair

I have a NSArray of NSDictionary objects:
[
{
id = 1;
fromDate = 2014-04-03;
toDate = 2014-04-05;
date = 0000-00-00;
title = title 1
},
{
id = 1;
fromDate = 0000-00-00;
toDate = 0000-00-00;
date = 2014-04-03
title = title 1
},
{
id = 1;
fromDate = 0000-00-00;
toDate = 0000-00-00;
date = 2014-04-04;
title = title 1
},
{
id = 2;
fromDate = 0000-00-00;
toDate = 0000-00-00;
date = 2014-05-10;
title = title 2
},
{
id = 2;
fromDate = 0000-00-00;
toDate = 0000-00-00;
date = 2014-05-11;
title = title 2
}
]
I would like to merge dictionaries with same id value into one dictionary combining all date, fromDate and toDate keys, obtaining an array like this, that ignores zero values:
[
{
id = 1,
combinedDates = 2014-04-03, 2014-04-05, 2014-04-03, 2014-04-04;
title = title 1
},
{
id = 2,
combinedDates = 2014-05-10, 2014-05-11;
title = title 2
}
]
Can someone point me to the right direction?
I don't know of any way to do this other than basic brute force:
-(NSArray*)combinedArray:(NSArray*)array
{
NSMutableArray* combined = [NSMutableArray new];
// Iterate over each unique id value
for(id key in [NSSet setWithArray:[array valueForKeyPath:#"id"]])
{
// skip missing keys
if([key isKindOfClass:[NSNull class]])
continue;
// Sub array with only id = key
NSArray* filtered = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSDictionary* evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject valueForKey:#"date"] && [[evaluatedObject valueForKey:#"id"] isEqual:key];
}]];
// Grab the dates
NSArray* dates = [filtered valueForKeyPath:#"date"];
// add the new dictionary
[combined addObject:#{ #"id":key, #"combinedDates":dates }];
}
return array;
}
// Group By id
-(NSMutableDictionary*)combinedArray:(NSArray*)array
{
NSMutableArray *categories = [[NSMutableArray alloc] init];
for (NSDictionary *data in array) {
NSString *category = [data valueForKey:#"id"];
if (![categories containsObject:category]) {
[categories addObject:category];
}
}
NSMutableDictionary *categoryData = [[NSMutableDictionary alloc]init];
for (NSString *strCat in categories) {
NSMutableArray *catArray = [[NSMutableArray alloc]init];
for (NSDictionary *data in array) {
NSString *category = [data valueForKey:#"id"];
if ([category isEqualToString:strCat]) {
[catArray addObject:data];
}
}
[categoryData setObject:catArray forKey:strCat];
}
return categoryData;
}

Resources