我正在尝试对一些字符串列表进行排序。元素的名称几乎可以是任何东西,包括真实姓名、字符串、日期……和数字。
我发现
NSStringCompareOptions
和 NSNumericSearch
,它的工作速度足够快,而且效果很好:
[1,2,21,3,55,6] --> [1,2,3,6,21,55]
但是我的问题是负数
[1,2,3,-1,-4,-5] --> [-1,-4,-5,1,2,3]
这是不对的。
我知道苹果说:
数字比较仅适用于字符串中的数字,不适用于在数字表示中有意义的其他字符,例如负号、逗号或小数点。
但我的问题是如何实现这一目标,因为我知道我不是唯一这样做的人。
编辑:
感谢Narendra Pandey,但我的真实案例有点复杂,所以他的答案不能用在这里。
假设我有一些字典,其中数字作为键,字符串作为值:
dic = {@1:@"123", @2:@"-123", @5:"MyName",...};
然后我就有了带有 ids 的对象数组。
array = @[{object with id 5}, {object with id 2},...];
我需要按属性名称对对象数组进行排序。
NSStringCompareOptions comparisonOption = NSCaseInsensitiveSearch | NSNumericSearch;
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = [dic objectForKey:obj1.someId];
NSString * name2 = [dic objectForKey:obj2.someId];
return [name1 compare:name2 options:comparisonOption];;
}];
编辑2:
也许我应该声明我有解决方案,但它比使用
NSStringCompareOptions
排序慢4倍
// CHECK IF IT IS NUMBER
NSNumber * number1 = [numberFormatter numberFromString:string1];
NSNumber * number2 = [numberFormatter numberFromString:string2];
//
// NSLog(@"NUMBERS : %@, %@", number1, number2);
if (number1 && number2) {
return [number1 compare:number2];
}
return [string1 compare:string2 options:comparisonOption];
NSArray * numbers = @[@1, @2, @3, @-4, @-5, @6, @9];
NSPredicate * predicateForPositive = [NSPredicate predicateWithFormat:@"integerValue >= 0"];
NSArray * positiveNumbers = [numbers filteredArrayUsingPredicate:predicateForPositive];
NSPredicate * predicateForNegative = [NSPredicate predicateWithFormat:@"integerValue <= 0"];
NSArray * NegativeNumber = [numbers filteredArrayUsingPredicate:predicateForNegative];
NSLog(@"Negative number %@",NegativeNumber);
NSLog(@"Positive number %@",positiveNumbers);
输出:
Negative number (
"-4",
"-5"
)
Positive number (
1,
2,
3,
6,
9
)
现在对两个数组进行排序并连接两个数组。
感谢 Narendra Pandey,我找到了解决方案。
首先声明,Narendra Pandey 解决方案有效,但速度较慢,甚至慢了 3 倍。
(在我的例子中,NSStringCompareOptions 为 0.014 秒,Narendra Pandey 解决方案为 0,042)。
但是如果我使用他的想法并稍微改变一下:
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = somehow get string1;
NSString * name2 = somehow get string2;
if ([string1 integerValue] <0 && [string2 integerValue]<0) {
return - [string1 compare:string2 options:comparisonOption];
}
return [string1 compare:string2 options:comparisonOption];
}];
这个方法更快,在我的例子中是 0,015 秒,与 NSStringCompareOptions 相当。
通过这种方式,您可以避免在开始时遍历整个数组来分离负数和正数,然后对它们进行排序。
此函数获取 any 数组并将其转换为排序 Double 数组
var numberArray: [Any] = [4, 3.9, -23,3, 7.6, -51, 75.3, "0", "-(22)"]
/// This function get any array and convert it to sorted _Double_ array
/// - Note: Non-numerical elements are automatically removed from the array
/// - Parameters:
/// - numbers: array of anything
/// - Returns: sorted _Double_ array
func sortAnyNumbers(_ numbers: [Any]) -> [Double] {
var _numbers: [Double] = []
numbers.forEach { number in
// Delete non-numeric characters
if let numb = Double("\(number)".components(separatedBy: CharacterSet(charactersIn: "-01234567890.").inverted).joined()) {
_numbers.append(numb)
}
}
return _numbers.sorted()
}
print(sortAnyNumbers(numberArray)) //[-51.0, -23.0, -22.0, 0.0, 3.0, 3.9, 4.0, 7.6, 75.3]