Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Update: see below for a better solution than my first one.</p> <p>Here's a solution using NSDictionary wrappers for each number and its index, with sorting using a comparator block. It probably doesn't scale very well, but it gets the job done.</p> <pre><code>static NSString *const kValueKey = @"value"; static NSString *const kIndexKey = @"index"; + (void)searchArray:(NSArray *)array forClosestValuesTo:(int)value resultValues:(NSArray **)values resultIndexes:(NSArray **)indexes { NSMutableArray *searchObjs = [NSMutableArray arrayWithCapacity:[array count]]; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [searchObjs addObject:[NSDictionary dictionaryWithObjectsAndKeys:obj, kValueKey, [NSNumber numberWithUnsignedInt:idx], kIndexKey, nil]]; }]; [searchObjs sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSUInteger d1 = ABS([[obj1 objectForKey:kValueKey] intValue] - value); NSUInteger d2 = ABS([[obj2 objectForKey:kValueKey] intValue] - value); if (d1 == d2) { return NSOrderedSame; } if (d1 &lt; d2) { return NSOrderedAscending; } return NSOrderedDescending; }]; NSArray *results = [searchObjs subarrayWithRange:NSMakeRange(0, 3)]; if (values) { *values = [results valueForKey:kValueKey]; } if (indexes) { *indexes = [results valueForKey:kIndexKey]; } } </code></pre> <p>Update: here's an updated solution that sorts a C array of indexes, eliminating the need for NSDictionary wrappers</p> <pre><code>static NSString *const kValueKey = @"value"; static NSString *const kArrayKey = @"array"; int CSCompareIndexes(void *data, const void *value1, const void *value2) { NSDictionary *dict = (NSDictionary *)data; NSArray *array = [dict objectForKey:kArrayKey]; int valueToFind = [[dict objectForKey:kValueKey] intValue]; int index1 = *(int *)value1; int index2 = *(int *)value2; NSNumber *num1 = [array objectAtIndex:index1]; NSNumber *num2 = [array objectAtIndex:index2]; return ABS([num1 intValue] - valueToFind) - ABS([num2 intValue] - valueToFind); } void CSSearchNumberArray(NSArray *array, int valueToFind, NSArray **resultValues, NSArray **resultIndexes) { NSInteger numValues = [array count]; NSUInteger *indexes = malloc(sizeof(NSUInteger) * numValues); assert(indexes); int i; for (i = 0; i &lt; numValues; i++) { indexes[i] = i; } NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:array, kArrayKey, [NSNumber numberWithInt:valueToFind], kValueKey, nil]; qsort_r(indexes, numValues, sizeof(NSUInteger), (void *)data, CSCompareIndexes); NSMutableArray *tmpValues = [NSMutableArray arrayWithCapacity:3], *tmpIndexes = [NSMutableArray arrayWithCapacity:3]; for (i = 0; i &lt; 3; i++) { [tmpValues addObject:[array objectAtIndex:indexes[i]]]; [tmpIndexes addObject:[NSNumber numberWithInt:indexes[i]]]; } if (resultValues) { *resultValues = [NSArray arrayWithArray:tmpValues]; } if (resultIndexes) { *resultIndexes = [NSArray arrayWithArray:tmpIndexes]; } free(indexes); } int main (int argc, char *argv[]) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; NSMutableArray *test = [NSMutableArray array]; int i; for (i = 0; i &lt; 10; i++) { [test addObject:[NSNumber numberWithInt:(arc4random() % 100)]]; } NSLog(@"Searching: %@", test); NSArray *values, *indexes; CSSearchNumberArray(test, 50, &amp;values, &amp;indexes); NSLog(@"Values: %@", values); NSLog(@"Indexes: %@", indexes); [pool drain]; return 0; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload