【问题标题】:Max value for each object in an Array of Dictionaries字典数组中每个对象的最大值
【发布时间】:2017-03-05 03:48:18
【问题描述】:

我有一个字典数组,我试图获取数组中每个玩家的最高分数。每个玩家可以有多个条目我试图获得每个玩家最好成绩的字典数组。

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

我尝试过使用 NSPredicate predicateWithFormat 但我只能取回数组中与名称无关的所有内容的最大值。

预期输出:

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

感谢您的帮助。

【问题讨论】:

  • 您是否尝试将 NameID 放入您的 NSPredicate 中?你是如何设置你的 NSPredicate 的?
  • 我不确定如何将 NameID 添加到谓词中并评估最大分数...我尝试了很多不同的方法,包括子查询,但我遗漏了一些东西...我试过了,但是后来发现完全错了... NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF.Score = NameID.@max.Score"];
  • 别想太多。只需遍历字典数组,随时构建输出字典。对于每个玩家 ID,只需根据输出字典中的分数(如果有)检查分数,并在需要时更新输出
  • 我想多了。以为我可以通过使用 NSPredicate 让它变得简单,但最终让它变得比我需要的更复杂......谢谢大家的回复。下面的一些答案没有按预期工作。我将我使用的那个标记为正确答案。

标签: ios objective-c arrays dictionary nspredicate


【解决方案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

【讨论】:

    【解决方案2】:

    你需要做的是找到每个用户的分数,然后找出它的最高分数。

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

    【讨论】:

      【解决方案3】:
      - (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];
      }
      

      【讨论】:

        【解决方案4】:

        试试这个:

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

        【讨论】:

          【解决方案5】:

          您可以像这样手动操作:

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

          【讨论】:

            【解决方案6】:

            您不能为此使用NSPredicate,因为您想确定几个不同玩家的最高分。在幕后,NSPredicate 无论如何都会迭代数组,因此使用您自己的循环并不会降低效率。在下面的代码中,我假设分数和玩家姓名包含在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];
            }
            

            【讨论】:

              猜你喜欢
              • 2021-09-13
              • 2017-01-04
              • 2017-01-25
              • 1970-01-01
              • 2017-08-09
              • 1970-01-01
              • 1970-01-01
              • 2020-03-16
              • 1970-01-01
              相关资源
              最近更新 更多