9

How do you get the largest value from an NSArray with dictionaries?

Lets say I have NSArray containing dictionaries with keys "age", "name", etc. Now I want to get the record with the highest age. Is this possible with some KVC magic? Or do I have to iterate through and do it the "manual" way?

I've tried with something similar to this:

int max = [[numbers valueForKeyPath:@"@max.intValue"] intValue];
Monolo
  • 18,205
  • 17
  • 69
  • 103
cmd
  • 129
  • 1
  • 5

2 Answers2

16

Unless "intValue" is a key in your dictionary the key path won't do much good.

If it is the max age you are after you should use @"@max.age" (on the dictionary) to get it. The same goes for any other key in your dictionary.

[myDictionary valueForKeyPath:@"@max.age"];

If numbers is an array of values you could use @"@max.self" as the key path to get the largest value.

[myArrayOfNumbers valueForKeyPath:@"@max.self"];
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
  • 1
    I am using your second line to get max element from my NSMutableArray (which contains all NSNumber objects inside) and I get this error: *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFNumber 0x1dd44bc0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key max.' Any idea what's wrong? – uerceg Mar 07 '13 at 10:50
  • I'm sorry. I assumed it would behave as NSPredicate and use `self` when nothing else was specified. The correct second example would be `[myArrayOfNumbers valueForKeyPath:@"@max.self"];` (answer updated) – David Rönnqvist Mar 07 '13 at 11:01
  • I thought you will propose this solution, but really strange thing is that this updated solution DOESN'T WORK for me neither. I get the same error message like before. – uerceg Mar 07 '13 at 11:11
  • 2
    Works for me, mutable or immutable. `NSArray *numbers = @[ @3, @5, @2.5, @(-5) ]; NSMutableArray *mutable = [NSMutableArray arrayWithArray:numbers]; NSNumber *largestValue = [numbers valueForKeyPath:@"@max.self"]; NSNumber *largestValueFromMutable = [mutable valueForKeyPath:@"@max.self"];` Gives correct result and no crashes. – David Rönnqvist Mar 07 '13 at 11:56
  • 1
    Arrrrgh! Sorry David for time I took you. I'm officially blind. I was constantly writing: valueForKeyPath:@"max.self" instead of valueForKeyPath:@"@max.self". (facepalm) Sorry and thank you once more! :) – uerceg Mar 07 '13 at 12:43
  • Heads up if anyone's having trouble here: you need to call `valueForKeyPath:` not `valueForKey:`. – rpowell Aug 16 '13 at 03:23
2

You're nearly there, you just need to specify the exact field you want from which you want the max value:

NSInteger max = [[numbers valueForKeyPath:@"@max.age"] integerValue];

I took the liberty to modify your ints to NSIntegers, just in case somebody wants to use this code on both iOS and OS X.

Monolo
  • 18,205
  • 17
  • 69
  • 103
  • 1
    This is a really good answer :) and it's different enough from the accepted answer to warrant an up vote – Rambatino Oct 29 '14 at 02:06