Unable to get all Matching string from NSDictionary iOS - 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.

Related

Searching in Dictionary of arrays in Objective C [duplicate]

i have a NSDictionary like:
{
"2017-05-02" = (
{
"always_valid" = 0;
date = "2017-05-02";
from = "12:00";
to = "13:00";
},
{
"always_valid" = 0;
date = "2017-05-02";
from = "12:00";
to = "12:00";
},
{
"always_valid" = 0;
date = "2017-05-02";
from = "14:00";
"hourly_rate" = 12;
to = "15:00";
}
);
"2017-05-03" = (
{
"always_valid" = 0;
date = "2017-05-03";
from = "12:00";
to = "13:00";
}
);
"2017-05-18" = (
{
"always_valid" = 1;
date = "2017-05-18";
from = "12:00";
to = "12:00";
}
);
}
i'm trying to apply
NSPredicate *filter = [NSPredicate predicateWithFormat:#"always_valid = \"1\""];
NSArray *alwaysvalid = [[dic allValues] filteredArrayUsingPredicate:filter];
it use to work when i had structure something like
array > dictionary
but now it's like
array > array > dictionary
by doing [dic allValues] for array.
any help what should i apply to keep it fast.
What you need to do is need enumerate your dictionary and create new filtered Dictionary.
NSMutableDictionary *filterDic = [[NSMutableDictionary alloc] init];
NSPredicate *filter = [NSPredicate predicateWithFormat:#"always_valid = 1"];
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSArray* obj, BOOL *stop) {
NSArray *filterArray = [obj filteredArrayUsingPredicate:filter];
if (filterArray.count > 0) {
filterDic[key] = filterArray;
}
}];
Try this :
NSArray *array = [NSArray arrayWithObject:dict]; // you can also do same for Name key...
NSArray *alwaysvalid = [array filteredArrayUsingPredicate:filter];

UITableview with multiple rows and sections

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.

Find out next most close date from NSDate array of times

How can I find out the next prayer from the array of times, I have total 6 Prayers at different times and i want to compare each one with current time and have to find out which one is most near as a next prayer, Date format also creating problems because it give always in UTC format and I have to use local time zone, I am using the following code:
NSMutableArray *arrayTimeIntervals = [[NSMutableArray alloc]init];
NSMutableArray *intervals = [[NSMutableArray alloc]init];
NSMutableArray *arrayPrayers = [[NSMutableArray alloc]init];
[arrayPrayers addObject:#{#"prayer":#"prayer 1",#"time":#"1:12 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 2",#"time":#"5:45 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 3",#"time":#"12:03 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"3:30 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"6:20 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 6",#"time":#"7:50 pm"}];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSMutableArray *dates = [NSMutableArray arrayWithCapacity:arrayPrayers.count];
for (NSDictionary *timeDict in arrayPrayers)
{
NSString *timeString = [timeDict objectForKey:#"time"];
NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
[dates addObject:#{#"prayer":name,#"time":timeString, #"date":date}];
}
for (int i =0 ; i<arrayPrayers.count; i++) {
NSDictionary *timeDict = arrayPrayers[i];
NSString *timeString = [timeDict objectForKey:#"time"];
//NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
NSComparisonResult result = [[NSDate date] compare:date];
if(result==NSOrderedAscending){
NSLog(#"next prayer");
}else if(result==NSOrderedDescending){
NSLog(#"last prayer");
}else{
NSLog(#"current prayer");
}
if ([date earlierDate:[NSDate date]]) {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSDictionary *tempDict = #{#"Prayer":timeDict,
#"Time":timeString,
#"Index":[NSString stringWithFormat:#"%d",i],
#"Interval":[NSString stringWithFormat:#"%f",interval]};
[arrayTimeIntervals addObject:tempDict];
[intervals addObject:[NSString stringWithFormat:#"%f",interval]];
}
}
NSNumber * min = [intervals valueForKeyPath:#"#min.doubleValue"];
NSUInteger index = 0;
for(int i =0 ; i<intervals.count; i++)
{
NSDictionary* dict = arrayTimeIntervals[i];
if([[dict objectForKey:#"Interval"] intValue] == [min intValue]) {
index = i;
NSLog(#"next prayer is!!!:%ld",index);
break;
}
}
NSDictionary *dict = [arrayTimeIntervals objectAtIndex:index];
NSLog(#"next prayer object is:%#",dict);

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];
}

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