RED*_*DMX 6 search objective-c nsarray
是否有一种简单的方法可以搜索NSArray数字以找到与用户输入数字匹配的最近(或确切存在)匹配?
假设我有一个这样的数组:7, 23, 4, 11, 18, 2,用户输入5.
该程序返回降序接近度的顺序的三个最近的值:4, 7, 2和最重要给出了NSArray三个对象的索引:2, 0, 5.
更新:请参阅下面的解决方案,比我的第一个更好.
这是使用NSDictionary包装器为每个数字及其索引提供的解决方案,使用比较器块进行排序.它可能不会很好地扩展,但它可以完成工作.
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];
}
}
Run Code Online (Sandbox Code Playgroud)
更新:这是一个更新的解决方案,可以对C数组索引进行排序,从而无需使用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;
}
Run Code Online (Sandbox Code Playgroud)