Shorty07
Shorty07

Reputation: 33

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.

Upvotes: 3

Views: 635

Answers (6)

Sushibu Sadanandan
Sushibu Sadanandan

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

Zeeshan Anjum
Zeeshan Anjum

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

hasan
hasan

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

Adeel Miraj
Adeel Miraj

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

alexburtnik
alexburtnik

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

Paulw11
Paulw11

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

Related Questions