Reputation: 33
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.
Upvotes: 3
Views: 635
Reputation: 1
// 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
Upvotes: 0
Reputation: 148
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];
}
Upvotes: -1
Reputation: 24185
- (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];
}
Upvotes: 0
Reputation: 2496
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);
Upvotes: 0
Reputation: 7741
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];
Upvotes: 1
Reputation: 114975
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];
}
Upvotes: 2