我有一些这样的数据:
1,111,2,333,45,67,322,4445
NSArray *array = [[myData allKeys]sortedArrayUsingSelector: @selector(compare:)];
如果我运行此代码,它的排序方式如下:
1,111,2,322,333,4445,45,67,
但我真的想要这个:
1,2,45,67,111,322,333,4445
我该如何实施?你好。
答案 0 :(得分:21)
扩展保罗林奇的答案,这是一个例子我使用比较方法作为NSString
上的类别正是这样做的。此代码仅处理数字后跟可选的非数字限定符的情况,但如果需要,您可以扩展它以处理“1a10”等情况。
创建类别方法后,您只需要
[[myData allKeys]sortedArrayUsingSelector:@selector(psuedoNumericCompare:)];
@interface NSString (Support)
- (NSComparisonResult) psuedoNumericCompare:(NSString *)otherString;
@end
@implementation NSString (Support)
// "psuedo-numeric" comparison
// -- if both strings begin with digits, numeric comparison on the digits
// -- if numbers equal (or non-numeric), caseInsensitiveCompare on the remainder
- (NSComparisonResult) psuedoNumericCompare:(NSString *)otherString {
NSString *left = self;
NSString *right = otherString;
NSInteger leftNumber, rightNumber;
NSScanner *leftScanner = [NSScanner scannerWithString:left];
NSScanner *rightScanner = [NSScanner scannerWithString:right];
// if both begin with numbers, numeric comparison takes precedence
if ([leftScanner scanInteger:&leftNumber] && [rightScanner scanInteger:&rightNumber]) {
if (leftNumber < rightNumber)
return NSOrderedAscending;
if (leftNumber > rightNumber)
return NSOrderedDescending;
// if numeric values tied, compare the rest
left = [left substringFromIndex:[leftScanner scanLocation]];
right = [right substringFromIndex:[rightScanner scanLocation]];
}
return [left caseInsensitiveCompare:right];
}
答案 1 :(得分:14)
您可以使用NSString的-[compare:options:]
函数和NSNumericSearch
选项以数字方式比较NSStrings,而不必先将它们转换为NSIntegers(这可能非常昂贵,尤其是在较长的循环中)。
由于你想使用NSArray,你可以使用NSSortDescriptor的+[sortDescriptorWithKey:ascending:comparator:]
(如果你想要一个预先保留的对象,可以使用相同的-initWithKey:ascending:comparator:
函数来执行基于块的比较:
[NSSortDescritor sortDescriptorWithKey:@"myKey"
ascending:NO
comparator:^(id obj1, id obj2)
{
return [obj1 compare:obj2 options:NSNumericSearch];
}
];
使用此方法排序将得到与David的答案相同的结果,但无需亲自处理NSScanner。
答案 2 :(得分:0)
实现自己的方法,返回NSComparisonResult
。如果您愿意,它可以属于一个类别。
答案 3 :(得分:0)
排序和简单解决方案..
NSSortDescriptor *sortDescriptor;
sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self"
ascending:YES
comparator:^(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [montharray
sortedArrayUsingDescriptors:sortDescriptors];
[montharray removeAllObjects];
[montharray addObjectsFromArray:sortedArray];
NSLog(@"MONTH ARRAY :%@",montharray);
答案 4 :(得分:0)
大卫的answer为我做了伎俩。对于它的价值,我想分享相同答案的Swift 1.0版本。
extension NSString {
func psuedoNumericCompare(otherString: NSString) -> NSComparisonResult {
var left: NSString = self
var right: NSString = otherString
var leftNumber: Int = self.integerValue
var rightNumber: Int = otherString.integerValue
var leftScanner: NSScanner = NSScanner(string: left)
var rightScanner: NSScanner = NSScanner(string: right)
if leftScanner.scanInteger(&leftNumber) && rightScanner.scanInteger(&rightNumber) {
if leftNumber < rightNumber {
return NSComparisonResult.OrderedAscending
}
if leftNumber > rightNumber {
return NSComparisonResult.OrderedDescending
}
left = left.substringFromIndex(leftScanner.scanLocation)
right = right.substringFromIndex(rightScanner.scanLocation)
}
return left.caseInsensitiveCompare(right)
}
}