How to group by the elements of an array in Objective C - ios

As mentioned here is possible with swift to How to group by the elements of an array : How to group by the elements of an array in Swift using this extension :
public extension SequenceType {
/// Categorises elements of self into a dictionary, with the keys given by keyFunc
func categorise<U : Hashable>(#noescape keyFunc: Generator.Element -> U) -> [U:[Generator.Element]] {
var dict: [U:[Generator.Element]] = [:]
for el in self {
let key = keyFunc(el)
if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
}
How to do the same with Objective C

Same results in Objective C. I tried this for your question and I got the solution now.It works fine.
NSArray *array = #[#{#"name" : #"lunch", #"date" : #"01-01-2015" , #"hours" : #"1"},
#{#"name" : #"dinner", #"date" : #"01-01-2015" , #"hours" : #"1"},
#{#"name" : #"dinner", #"date" : #"01-01-2015" , #"hours" : #"1"},
#{#"name" : #"lunch", #"date" : #"01-01-2015" , #"hours" : #"1"},
#{#"name" : #"dinner", #"date" : #"01-01-2015" , #"hours" : #"1"},
];
NSMutableArray *resultLunchArray = [NSMutableArray new];
NSMutableArray *resultDinnerArray = [NSMutableArray new];
NSMutableArray *finalResultsArray = [NSMutableArray new];
NSArray *groupLunch = [array valueForKeyPath:#"#distinctUnionOfObjects.name"];
for (NSString *str in groupLunch)
{
NSArray *groupNames = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"name = %#", str]];
if([str isEqualToString:#"lunch"])
{
for (int i = 0; i < groupNames.count; i++)
{
NSString *nameLunch = [[groupNames objectAtIndex:i] objectForKey:#"name"];
NSString *dateLunch = [[groupNames objectAtIndex:i] objectForKey:#"date"];
NSString *strNameLunch = [NSString stringWithFormat:#"%# : %#",nameLunch,dateLunch];
[resultLunchArray addObject:strNameLunch];
}
[finalResultsArray addObject:resultLunchArray];
}
else{
for (int i = 0; i < groupNames.count; i++)
{
NSString *nameDinner = [[groupNames objectAtIndex:i] objectForKey:#"name"];
NSString *dateDinner = [[groupNames objectAtIndex:i] objectForKey:#"date"];
NSString *strNameDinner = [NSString stringWithFormat:#"%# : %#",nameDinner,dateDinner];
[resultDinnerArray addObject:strNameDinner];
}
[finalResultsArray addObject:resultDinnerArray];
}
}
NSLog(#"The final results are - %#",finalResultsArray);
The Output Reults are
The final results are - (
(
"lunch : 01-01-2015",
"lunch : 01-01-2015"
),
(
"dinner : 01-01-2015",
"dinner : 01-01-2015",
"dinner : 01-01-2015"
)
)

Related

Max value for each object in an Array of Dictionaries

I have an array of dictionaries that I am trying to get the Max score for each player in the array. Each player can have multiple entries I am trying to get an array of dictionaries of each players best score.
NSArray
[0] - NSDictionary
- [0] Score: (double)20.7
- [1] NameID: (int) 1
- [2] Date
[1] - NSDictionary
- [0] Score: (double)25
- [1] NameID: (int) 1
- [2] Date
[2] - NSDictionary
- [0] Score: (double)28
- [1] NameID: (int) 2
- [2] Date
[3] - NSDictionary`
- [0] Score: (double)26
- [1] NameID: (int) 3
- [2] Date
I have tried using NSPredicate predicateWithFormat but I am only able to get back the max for everything in the array not related to the name.
Expected Output:
NSArray
[1] - NSDictionary
- [0] Score: (double)25
- [1] NameID: (int) 1
- [2] Date
[2] - NSDictionary
- [0] Score: (double)28
- [1] NameID: (int) 2
- [2] Date
[3] - NSDictionary`
- [0] Score: (double)26
- [1] NameID: (int) 3
- [2] Date
Thanks for the help.
You can't use an NSPredicate for this, since you want to determine the maximum score for several different players. Under the covers, NSPredicate iterates the array anyway, so using your own loop isn't any less efficient. In the following code I have assumed that the scores and player names are wrapped in NSNumber
-(NSArray *)maxScoresForPlayers:(NSArray *)playerScores {
NSMutableDictionary *maxScores = [NSMutableDictionary new];
for (NSDictionary *player in playerScores) {
NSNumber *playerID = (NSNumber *)player[#"NameID"];
NSDictionary *playerMax = maxScores[playerID];
if (playerMax == nil) {
playerMax = player;
} else {
NSNumber *currentMax = (NSNumber *)[playerMax[#"Score"];
NSNumber *playerScore = (NSNumber *)player[#"Score"];
if ([playerScore doubleValue] > [currentMax doubleValue]) {
playerMax = player;
}
}
maxScores[playerID] = playerMax;
}
return([maxScores allValues];
}
You can do it manually like this:
NSMutableDictionary *maxScoresDict = [NSMutableDictionary dictionary];
for (NSDictionary *score in scoresArray) {
NSNumber *key = score[#"NameID"];
NSNumber *savedMax = maxScoresDict[key][#"Score"];
NSNumber *currentMax = maxScoresDict[key][#"Score"];
if (savedMax == nil || [currentMax doubleValue] > [savedMax doubleValue]) {
maxScoresDict[key] = score;
}
}
NSArray *maxScoresArray = [maxScoresDict allValues];
Try this:
NSArray *objects = #[#{#"Score": #(20.7),
#"NameID": #(1),
#"Date": [NSDate date]},
#{#"Score": #(25),
#"NameID": #(1),
#"Date": [NSDate date]},
#{#"Score": #(28),
#"NameID": #(2),
#"Date": [NSDate date]},
#{#"Score": #(26),
#"NameID": #(3),
#"Date": [NSDate date]}];
NSMutableArray *users = [NSMutableArray array];
for (NSInteger i=0; i<objects.count; i++) {
NSDictionary *dict = objects[i];
NSNumber *nameID = dict[#"NameID"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.NameID==%#", nameID];
NSInteger index = [users indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL found = [predicate evaluateWithObject:obj];
return found;
}];
if (index != NSNotFound) {
NSNumber *score1 = dict[#"Score"];
NSNumber *score2 = users[index][#"Score"];
if (score1.doubleValue > score2.doubleValue) {
[users replaceObjectAtIndex:index withObject:dict];
}
}
else {
[users addObject:dict];
}
}
NSLog(#"%#", users);
- (NSArray *)getBestScores:(NSArray *)players {
NSMutableDictionary *best = [[NSMutableDictionary alloc] init];
for (NSDictionary *p in players) {
NSDictionary *b = [best valueForKey:[p valueForKey:#"NameID"]];
if (!b || [[p valueForKey:#"Score"] doubleValue] > [[b valueForKey:#"Score"] doubleValue])
[best setValue:p forKey:[p valueForKey:#"NameID"]];
}
return [best allValues];
}
// Get Max Value of integer element from Array of Dictonaries.
// Example Array Starts
<paramArray>(
{
DicID = 1;
Name = "ABC";
ValuetoCalculateMax = 2800;
},
{
DicID = 2;
Name = "DEF";
ValuetoCalculateMax = 2801;
},
{
DicID = 3;
Name = "GHI";
ValuetoCalculateMax = 2805;
}
)
// Example Array Ends
// Implementation
int MaxintegerValue=0;
MaxintegerValue=[self getMaxValueFromArrayofDictonaries:paramArray];
// Implementation Ends
// Function Starts
-(int)getMaxValueFromArrayofDictonaries:(NSArray *)paramArray
{
int MaxValue=0;
NSMutableDictionary *dic=[[NSMutableDictionary alloc]init];
for ( int i=0; i<[paramArray count]; i++ )
{
dic=[paramArray objectAtIndex:i];
if ([[dic valueForKey:#"ValuetoCalculateMax"] intValue] > MaxValue)
{
MaxValue=[[dic valueForKey:#"ValuetoCalculateMax"] intValue];
}
else
{
MaxValue=MaxValue;
}
}
return MaxValue;
}
// Function Ends
What you need to do is find scores for each user, then find the max score out of it.
- (void)findMaxScoreForUser:(int)userId {
NSDictionary *dict0 = [NSDictionary dictionaryWithObjects:#[#27.0,#3] forKeys:#[#"Score",#"UserID"]];
NSDictionary *dict1 = [NSDictionary dictionaryWithObjects:#[#25.0,#2] forKeys:#[#"Score",#"UserID"]];
NSDictionary *dict2 = [NSDictionary dictionaryWithObjects:#[#23.0,#3] forKeys:#[#"Score",#"UserID"]];
NSArray *arr = [NSArray arrayWithObjects:dict0,dict1,dict2, nil];
NSMutableArray *scores = [NSMutableArray array];
for (NSDictionary *dict in arr) {
int userID = [[dict valueForKey:#"UserID"] intValue];
if (userId == userID) {
[scores addObject:[dict valueForKey:#"Score"]];
}
}
int max = [[scores valueForKeyPath:#"#max.intValue"] intValue];
}

how to remove duplicates from array of dictionary for a specific key

{
distance = "0.03159804520191554";
rid = 374824705969;
uuid = "1838346268_374823983610_2016-08-08T07:32:08.679GMT";
},
{
rid = 374824705969;
uuid = "1838346268_374823983610_2016-08-08T07:32:08.679GMT";
},
{
rid = 374824706065;
uuid = "1838346268_374823983610_2016-08-08T07:32:22.680GMT";
}
This is what I got from the array of dictionaries. I want to remove duplicates where rid=374824705969 without using loops.Can any one help me.
Thanks in advance.
Try these one:
NSArray *array = #[
#{
#"rid" : #374824705969,
#"uuid" : #"1838346268_374823983610_2016-08-08T07:32:08.679GMT"
},
#{
#"rid" : #374824705969,
#"uuid" : #"1838346268_374823983610_2016-08-08T07:32:08.679GMT"
},
#{
#"rid" : #374824706065,
#"uuid" : #"1838346268_374823983610_2016-08-08T07:32:22.680GMT"
}];
NSMutableSet *keys = [NSMutableSet new];
NSMutableArray *result = [NSMutableArray new];
for (NSDictionary *data in array) {
NSString *key = data[#"rid"];
if ([keys containsObject:key]) {
continue;
}
[keys addObject:key];
[result addObject:data];
}
NSLog(#"%#", result);

IOS: how to join 2 Dictionaries into 1 dictionary??

in my project i applied the following code
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSLog(#" for ref id =%# ,name of diagnose=%# data is= %#",refidstr,diagnosedictforname ,diagnosisdict);
and the output in console is comes out as in the form
str : {
diagnoses = (
{
Diagnoses = {
"diagnosis_name" = "TRANSIENT ISCHEMIA";
};
DiagnosesHospitals = {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
};
}
);
response = 200;
}
ref id =3341 ,name of diagnose={
"diagnosis_name" = "TRANSIENT ISCHEMIA";
} data is= {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
}
now i just want to embed the values of both the Dictionaries into one dictionary
someone please help me to sort out this issue.
Make a mutable copy of the first dictionary:
NSMutableDictionary * mutDic = [dic1 mutableCopy];
and then:
[mutDic addEntriesFromDictionary:dic2];
Try this code:
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
NSMutableDictionary *diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
NSDictionary *diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSArray *keys = [diagnosedictforname allKeys];
for (int i =0; i < keys.count; i++) {
NSString *key = [keys objectAtIndex:i];
[diagnosisdict setValue:[diagnosedictforname valueForKey:key] forKey:key];
}
NSLog(#"your dic -> %#", diagnosisdict);

ios NSPredicate to find nearest value in NSDictionary

I have an array of dictionaries like this:
(
{ key = 1, value = 40},
{ key = 4, value = 50},
{ key = 8, value = 60}
}
These are like this,
for >=1 item cost is 40,
for >=4 item cost is 50 and like wise.
I would like to get the value for 5, which in this case is 50.
The piece of code I have tried is:
NSMutableArray *wallpaperPriceArray = [[NSMutableArray alloc]init]; // Assuming this has all the dictionary values
float wallpaperPriceValue = 0;
int itemNumber = 0;
for (int i = 0; i<wallpaperPriceArray.count; i++) {
int check = 0;
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i] objectForKey:#"value"] floatValue];
check++;
}
if(i + 1 <= wallpaperPriceArray.count)
{
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i+1] intValue] && itemNumber < [[wallpaperPriceArray objectAtIndex:i+1] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i+1] objectForKey:#"value"] floatValue];
check++;
if(check == 2)
{
break ;
}
}
}
if(i + 2 <= wallpaperPriceArray.count)
{
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i+2] intValue] && itemNumber < [[wallpaperPriceArray objectAtIndex:i+2] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i+2] objectForKey:#"value"] floatValue];
check++;
if(check == 2)
{
break ;
}
}
}
I Don't think the predicate is the right thing, Better would be to enumerate the objects here is some sample code:
NSArray *array = #[
#{ #"key" : #(1), #"value" : #(40)},
#{ #"key" : #(4), #"value" : #(50)},
#{ #"key" : #(8), #"value" : #(60)}
];
NSInteger searchedValue = 5; // <---
__block NSDictionary *closestDict = nil;
__block NSInteger closestValue = 0;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *dict = obj;
NSInteger key = [dict[#"key"] integerValue];
// Check if we got better result
if(closestDict == nil || (key > closestValue && key <= searchedValue)){
closestDict = dict;
closestValue = key;
if(key == searchedValue) { *stop = YES; }
}
}];
NSLog(#"value %#", closestDict);
I would suggest in addition to above answer to use the spline method to get the value needed, this is in the link
https://github.com/soffes/SAMCubicSpline
Using this library would solve the question as follows:
NSArray *array = #[
#{ #"key" : #(1), #"value" : #(40)},
#{ #"key" : #(4), #"value" : #(50)},
#{ #"key" : #(8), #"value" : #(60)}];
SAMCubicSpline *spline = [[SAMCubicSpline alloc] initWithPoints:#[
[NSValue valueWithCGPoint:CGPointMake(1.0f, 40.0f)],
[NSValue valueWithCGPoint:CGPointMake(4.0f, 50f)],
[NSValue valueWithCGPoint:CGPointMake(8.0f, 60.0f)],
]];
then you can obtain any value by this
CGFloat y = [spline interpolate:x];

count occurrences in a NSArray

this is a part of my code from a NSArray:
2012-06-03 16:03:45.140 test[4178:f803] data (
{
receiver = david;
sender = james;
idMessage = 248;
},
{
receiver = david;
sender = james;
idMessage = 247;
},
{
receiver = david;
sender = Marc;
idMessage = 246;
}
)
I want the number of messages sent by sender to receiver or something like that
james = 2;
marc = 1;
"data" is the NSArray, which appears to contain NSDictionary objects.
So you'd want to loop through the array this way:
NSNumber * countOfSender;
NSString * nameOfSender;
NSMutableDictionary * countDictionary = [[NSMutableDictionary alloc] initWithCapacity: 1];
// go through the original array to examine each sender
for(NSDictionary *anEntry in data)
{
nameOfSender = [anEntry objectForKey: #"sender"];
if(sender)
{
countOfSender = [countDictionary objectForKey: nameOfSender];
if(countOfSender == NULL)
{
// create a new count entry for this particular sender
countOfSender = [NSNumber numberWithInt: 1];
} else {
// increment the previous count
countOfSender = [NSNumber numberWithInt: [countOfSender intValue] + 1];
}
[countDictionary setObject: countOfSender forKey: nameOfSender];
}
}
// now print out the outputs
for(nameOfSender in [countDictionary allKeys])
{
countOfSender = [countDictionary objectForKey: nameOfSender];
NSLog( #"%# : %d" nameOfSender, [countOfSender intValue] );
}
You would do something like..
NSMutableArray *array = [NSMutableArray array];
for(id object in yourArray) {
NSLog("sender:%# id:%i",[object valueForKey:#"sender"],[[object valueForKey:#"idMessage"] intValue]);
NSMutableDictionary *dict = [
NSMutableDictionary dictionary];
[dict setValue:[object valueForKey:#"sender"] forKey:#"sender"];
[dict setValue:[NSNumber numberWithInt:[[object valueForKey:#"idMessage"] intValue]] forKey:#"idMessage"];
[array addObject:dict];
}
NSLog(#"%#",array);

Resources