views:

30

answers:

1

How would I search my dictionary for the closest value to the query? Say I search for 0.000475, I know it's not available but I want to return it's closest value 0.000500.

I suppose I would use keysOfEntriesPassingTest to achieve this on a dictionary, clueless on how to go about it though.

<key>1/8000</key><real>0.000125</real> 
<key>1/6400</key><real>0.000156</real> 
<key>1/5000</key><real>0.000200</real> 
<key>1/4000</key><real>0.000250</real> 
<key>1/3200</key><real>0.000313</real> 
<key>1/2500</key><real>0.000400</real> 
<key>1/2000</key><real>0.000500</real> 
<key>1/1600</key><real>0.000625</real> 
A: 

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.

ig2r
Thanks, that worked out. I'll look into enumerateKeysAndObjectsUsingBlock. Just getting my feet wet with objective c
Ronn