Since keysOfEntriesPassingTest
returns a set of values, it would be better suited to a task like finding all keys that are within a given epsilon range from your query value, but not finding the single closest key like in this case.
So here's one way to do it, although it certainly is a bit inefficient:
NSDictionary* dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0],
[NSNumber numberWithFloat:2.0],
[NSNumber numberWithFloat:3.0], nil]
forKeys:[NSArray arrayWithObjects:@"foo", @"bar", @"baz", nil]];
float query = ...;
NSArray* matches = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) {
NSNumber* x = [NSNumber numberWithFloat:fabs([obj1 floatValue] - query)];
NSNumber* y = [NSNumber numberWithFloat:fabs([obj2 floatValue] - query)];
return [x compare:y];
}];
[matches objectAtIndex:0]
will then hold the key of the value with the best match, index 1 the key to the second-best match, etc.
edit: yap, if you don't need the other matches, it's almost certainly a better idea to just call enumerateKeysAndObjectsUsingBlock:
in conjunction with a variable outside the passed block that holds the key/value of the closest match found so far and updates it if the current value is closer to the query value.