Max value for each object in an Array of Dictionaries - ios

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

Related

search in an nsarray of nsdictionaries performance memory optimised way

this question is based on performance, i am getting desired results.
i have a array of dictionaries like this:
Printing description of arrAppointmentDictionary:
<__NSArrayM 0x16f962a0>(
{
"component_id" = 159;
total = 1;
},
{
"component_id" = 165;
total = 1;
},
{
"component_id" = 177;
total = 1;
},
{
"component_id" = 191;
total = 1;
},
{
"component_id" = 193;
total = 1;
}
)
i searched in dictionary based on keys like this:
for (int i = 0; i<arrAppointmentDictionary.count; i++)
{
NSMutableDictionary *appointmentDictionary = [arrAppointmentDictionary objectAtIndex:i];
NSArray *keys = [appointmentDictionary allKeys];
for (NSString *key in keys)
{
#autoreleasepool {
NSLog(#"Key is %#", key);
if([[appointmentDictionary objectForKey: key] isEqualToString:[rs stringForColumn:#"id"]])
{
layout.numberOfAppointments = [appointmentDictionary objectForKey: #"total"];
NSLog(#"number of appointments are >>>>>>>>>>>>>>>>> %#", [appointmentDictionary objectForKey: #"total"]);
}
}
}
}
i get the results accurate.
how to increase performance/memory optimisations of this for loop as it is called from another while loop.
thanks & regards.
Here's one way:
NSString *wantedId = [rs stringForColumn:#"id"];
for (NSMutableDictionary *appointmentDictionary in arrAppointmentDictionary) {
if ([appointmentDictionary[#"id"] isEqualToString:wantedId]) {
layout.numberOfAppointments = appointmentDictionary[#"total"];
NSLog(#"number of appointments are >>>>>>>>>>>>>>>>> %#", appointmentDictionary[#"total"]);
break;
}
}

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

NSDictionary order does not match allKeys order

I've created NSDictionary of sorted arrays by name organized by first letter (see results below). When I use the command allKeys for that same Dictionary, the order is not the same. I need the order the same because this NSDictionary is used in UITableview and should be alphabetical.
- (NSDictionary*) dictionaryNames {
NSDictionary *dictionary;
NSMutableArray *objects = [[NSMutableArray alloc] init];
NSArray *letters = self.exhibitorFirstLetter;
NSArray *names = self.exhibitorName;
for (NSInteger i = 0; i < [self.exhibitorFirstLetter count]; i++)
{
[objects addObject:[[NSMutableArray alloc] init]];
}
dictionary = [[NSDictionary alloc] initWithObjects: objects forKeys:letters];
for (NSString *name in names) {
NSString *firstLetter = [name substringToIndex:1];
for (NSString *letter in letters) { //z, b
if ([firstLetter isEqualToString:letter]) {
NSMutableArray *currentObjects = [dictionary objectForKey:letter];
[currentObjects addObject:name];
}
}
}
NSLog(#"%#", dictionary);
NSLog(#"%#", [dictionary allKeys]);
return dictionary;
}
B = (
"Baker's Drilling",
"Brown Drilling"
);
C = (
"Casper Drilling"
);
J = (
"J's, LLC"
);
N = (
"Nelson Cleaning",
"North's Drilling"
);
T = (
"Tim's Trucks"
);
Z = (
"Zach's Main",
"Zeb's Service",
"Zen's"
);
}
J,
T,
B,
N,
Z,
C
)
NSDictionary is not an ordered collection. There's no way to control how it orders things, and it may change completely depending on OS version, device type, and dictionary contents.
I just put the NSDictionary in sorted array:
- (NSArray*)sortAllKeys:(NSArray*)passedArray{
NSArray* performSortOnKeys = [passedArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
return performSortOnKeys;
}

Compare 2 nsmutablearray and get different object to third array in ios

I want to compare 2 NSMutableArray and get different object into third Array. How can i do that ?
Array1 can loop object .
Array1 = "a", "b","c","d","a","b","c";
Array2 = "a", "b", "c";
And then result
Array3 = "d";
Thanks in advance
Use sets for set operations:
NSSet *set1 = [NSSet setWithArray:array1];
NSMutableSet *set2 = [NSMutableSet setWithArray:array2];
[set2 minusSet:set1];
You Can try this too.
NSMutableArray *array1 = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"1", nil];
NSMutableArray *array2 = [[NSMutableArray alloc]initWithObjects:#"2",#"1", nil];
NSMutableArray *largeArray;
NSMutableArray *shortArray;
if([array1 count] > [array2 count]){
largeArray = array1;
shortArray = array2;
} else {
largeArray = array2;
shortArray = array1;
}
[largeArray removeObjectsInArray:shortArray];
for (NSString *va in largeArray) {
NSLog(#"%#",va);
}
NSMutableArray *gotDiffArry= [[NSMutableArray alloc] init];
for(int i = 0 ; i < FirstArray.count; i++) {
if(i < seconArray.count){
if(![seconArray[i] isEqual:firstArray[i]]){
[gotDiffArry addObject:[NSNumber numberWithInt:i]];
}
} else {
[gotDiffArry addObject:[NSNumber numberWithInt:i]];
}
}
EDITED:
for (int i = 0 ; i < firstArray.count ; i ++)
{
NSString *search = [firstArray objectAtIndex:i];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF CONTAINS %#", search];
NSMutableArray *temAraay = [secondArray filteredArrayUsingPredicate: predicate];
if(temArray.count >=0 )
{
NSLog("%#", [temArray objectAtIndex:0]);
}
}
I have used the following and got the desired results:
for(int i =0; i<[arraytwo count]; i++)
{
if (![arrayone containsObject:[arraytwo objectAtIndex:i]])
[arraythree addObject: [arraytwo obectAtIndex:i]];
}
NSLog(#"%#",arraythree);

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