使用比较器对NSDictionaries的NSArray进行sorting

我一直在尝试使用比较器对NSDictionaries的NSArray进行sorting,但我似乎无法得到我想要的输出。

我试图达到的输出是,AZ的用户名应该排在第一位的sorting数组,然后以数字开头的用户名应该排在第二位的sorting数组,最后用户名以下划线开始应该在sorting的数组中最后。 任何帮助真正感激!

编辑:它应该被sorting,所以它看起来整个NSArray一致,以便:_Anna之前_Bob和_11Bob之前_12Cary但之后_09Bob

我期待的输出示例:

( { username = abcd; }, { username = Anna; }, { username = 01Bob; }, { username = 02Tob; }, { username = 03ZED; }, { username = 04_Hob; }, { username = 04_sob; }, { username = "_anna"; }, { username = "_bob"; }, { username = "_boc"; }, { username = "_bocd12"; }, { username = "_bocd13"; } { username = _01Bob; }, { username = _02Tob; }, ) 

我希望现在有道理。

使用NSDrayaries的NSArray示例NSDictionary:

 NSDictionary *dictionary = @{@"users":@[@{@"username":@"191anna"},@{@"username":@"_091bob"},@{@"username":@"Bob"},@{@"username":@"charlie"}]}; 

我正在尝试使用这个比较器:

 NSArray *array = [[dictionary objectForKey:@"users"] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSString *f1 = [obj1 objectForKey:@"username"]; NSString *f2 = [obj2 objectForKey:@"username"]; NSString *s1 = [[obj1 objectForKey:@"username"]substringFromIndex:1]; NSString *s2 = [[obj2 objectForKey:@"username"]substringFromIndex:1]; if ([s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location == [s2 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location) { return [f1 localizedCaseInsensitiveCompare:f2]; } else if ([s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != [s2 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location) { return [f1 localizedCaseInsensitiveCompare:f2]; if ([s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location == NSNotFound) { return NSOrderedDescending; } } return NSOrderedAscending; }]; 

但它给了我以下(不是我想要的)sortingNSArray:

 ( { username = "_091bob"; }, { username = 191anna; }, { username = Bob; }, { username = charlie; } ) 

这是我想出来的。 这是一个很长的触摸,因为它需要相当多的逻辑。 它可能会进一步优化:

我的设置:

 NSArray * usernames = @[@"191anna", @"abcd", @"Anna", @"01Bob", @"02Tob", @"03ZED", @"04_rob", @"_anna", @"_bob", @"_boc", @"_bocd12", @"_bocd13", @"_01Bob", @"_02Tob"]; NSMutableArray * users = [NSMutableArray array]; for (NSString * username in usernames) { [users addObject:@{@"username":username}]; } NSDictionary * dictionary = @{@"users":users}; 

和sorting:

 NSArray *sortedArray = [dictionary[@"users"] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSString *nameOne = obj1[@"username"]; NSString *nameTwo = obj2[@"username"]; NSString *startOne; NSString *startTwo; NSInteger currentIndex = 0; NSInteger maxIndex = (nameOne.length < nameTwo.length) ? nameOne.length : nameTwo.length; // Get our first differentiating letter do { if (currentIndex < maxIndex) { startOne = [nameOne substringWithRange:NSMakeRange(currentIndex, 1)]; startTwo = [nameTwo substringWithRange:NSMakeRange(currentIndex, 1)]; currentIndex++; } else { // Names are equal up to max length. Same length is same, else shorter word ascending. (bob above bobb) if (nameOne.length == nameTwo.length) { return NSOrderedSame; } else { return (nameOne.length < nameTwo.length) ? NSOrderedAscending : NSOrderedDescending; } } } while ([startOne isEqualToString:startTwo]); // Prioritize underscores to bottom NSCharacterSet * underscoreCharSet = [NSCharacterSet characterSetWithCharactersInString:@"_"]; NSRange underscoreRangeOne = [startOne rangeOfCharacterFromSet:underscoreCharSet]; NSRange underscoreRangeTwo = [startTwo rangeOfCharacterFromSet:underscoreCharSet]; if (underscoreRangeOne.length > 0 || underscoreRangeTwo.length > 0) { // Something is underscored, put it on the bottom return (underscoreRangeOne.length > 0) ? NSOrderedDescending : NSOrderedAscending; } // Prioritize numbers to bottom NSRange decimalRangeOne = [startOne rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]]; NSRange decimalRangeTwo = [startTwo rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]]; if (decimalRangeOne.length > 0 || decimalRangeTwo.length > 0) { // Something is numbered, put it on the bottom if (decimalRangeOne.length == decimalRangeTwo.length) { return (startOne.intValue > startTwo.intValue) ? NSOrderedDescending : NSOrderedAscending; } else if (decimalRangeOne.length > decimalRangeTwo.length) { return NSOrderedDescending; } else if (decimalRangeTwo.length > decimalRangeOne.length) { return NSOrderedAscending; } } // Now, sort alphabetically return [nameOne localizedCaseInsensitiveCompare:nameTwo]; }]; NSLog(@"SortedArray: %@", sortedArray); 

将日志logging为:

 abcd, Anna, 01Bob, 02Tob, 03ZED, "04_rob", 191anna, "_anna", "_bob", "_boc", "_bocd12", "_bocd13", "_01Bob", "_02Tob" 

你可以进一步优化,但你的sorting逻辑将如下所示。

  NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSString *name1 = [(NSDictionary *) obj1 objectForKey:NAME]; NSString *name2 = [(NSDictionary *) obj2 objectForKey:NAME]; if ([name1 characterAtIndex:0] == '_' && [name2 characterAtIndex:0] == '_') { return [name1 compare:name2 options:NSCaseInsensitiveSearch]; } else if ([name1 characterAtIndex:0] == '_') { return NSOrderedDescending; } else if ([name2 characterAtIndex:0] == '_') { return NSOrderedAscending; } else if (([name1 intValue] && [name2 intValue]) || ([name1 characterAtIndex:0] == '0' && [name2 characterAtIndex:0] == '0')) { return [name1 compare:name2 options:NSCaseInsensitiveSearch]; } else if ([name1 intValue] >0 || [name1 characterAtIndex:0] == '0') { return NSOrderedDescending; } else if ([name2 intValue]>0 || [name2 characterAtIndex:0] == '0') { return NSOrderedAscending; } else { return [name1 compare:name2 options:NSCaseInsensitiveSearch]; } //return res; }];