Cập nhật: xem dưới đây để biết một giải pháp tốt hơn so với một đầu tiên của tôi.
Đây là giải pháp sử dụng trình bao bọc NSDictionary cho mỗi số và chỉ mục của nó, với phân loại bằng khối so sánh. Nó có thể không quy mô rất tốt, nhưng nó được thực hiện công việc.
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 < d2) { return NSOrderedAscending; }
return NSOrderedDescending;
}];
NSArray *results = [searchObjs subarrayWithRange:NSMakeRange(0, 3)];
if (values) {
*values = [results valueForKey:kValueKey];
}
if (indexes) {
*indexes = [results valueForKey:kIndexKey];
}
}
Cập nhật: đây là một giải pháp cập nhật mà sắp xếp một mảng C các chỉ số, loại bỏ sự cần thiết của giấy gói NSDictionary
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 < 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 < 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 < 10; i++) {
[test addObject:[NSNumber numberWithInt:(arc4random() % 100)]];
}
NSLog(@"Searching: %@", test);
NSArray *values, *indexes;
CSSearchNumberArray(test, 50, &values, &indexes);
NSLog(@"Values: %@", values);
NSLog(@"Indexes: %@", indexes);
[pool drain];
return 0;
}
Tôi nghĩ cách dễ nhất là tìm kiếm inimun số, loại bỏ nó, và tìm số minimun một lần nữa, vv – TommyG
Tôi bắt đầu bằng cách viết một vòng lặp cho rằng kiểm tra từng số, nhưng tôi nhanh chóng nhận ra rằng tôi sẽ không thể có được chỉ số của các đối tượng từ bản gốc mảng. Việc tìm kiếm chỉ mục đó rất quan trọng đối với chương trình thực tế của tôi - những gì tôi đăng ở đây là một ví dụ đơn giản để tôi có thể tìm hiểu lý thuyết – REDMX
nó khá đơn giản để theo dõi chỉ mục ban đầu của số bạn tìm thấy, nhưng bạn có thể làm điều đó mà không cần sửa đổi mảng. Giả sử bạn tìm min, bạn giữ chỉ mục của nó (đó là số đầu tiên của bạn trong số ba), sau đó thay vì xóa nó, bạn có thể thay thế bằng số tối đa - theo cách này, bạn không thay đổi mảng của mình .... – TommyG