我一直在尝试使用比较器对NSArray NSArray进行排序,但我似乎无法获得我想要的输出。
我想要实现的输出是AZ用户名应该在排序数组中排在第一位,然后以数字开头的用户名应该在排序数组中排在第二位,最后以下划线开头的用户名应该是最后一位排序的数组。真的很感激任何帮助!
编辑:它应该被排序,以便它在整个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;
},
)
我希望现在有道理。
使用NSDrray的NSDrray示例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;
}];
但它给了我以下(不是我想要的方式)排序的NSArray:
(
{
username = "_091bob";
},
{
username = 191anna;
},
{
username = Bob;
},
{
username = charlie;
}
)
答案 0 :(得分:1)
您可以进一步优化,但您的排序逻辑将如下所示。
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;
}];
答案 1 :(得分:1)
这就是我想出的。这需要很长时间,因为它需要相当多的逻辑。它可能会进一步优化:
我的设置:
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};
和排序:
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);
将记录为:
abcd,
Anna,
01Bob,
02Tob,
03ZED,
"04_rob",
191anna,
"_anna",
"_bob",
"_boc",
"_bocd12",
"_bocd13",
"_01Bob",
"_02Tob"