在 iOS 中對包含字典的數組按價格字段排序,若價格存儲為字串 (NSString),需使用 localizedStandardCompare: 選擇器正確處理數字字串比較,避免字典序導致 "10" < "2" 的問題。
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"Price" ascending:YES];
// 錯誤:字串比較 "0.715" vs "10.5" 按字典序,結果錯誤
NSArray *sorted = [symbolArray sortedArrayUsingDescriptors:@[sort]];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"Price"
ascending:YES
selector:@selector(localizedStandardCompare:)];
// 關鍵:selector 參數指定比較方法
NSArray *sortedArray = [symbolArray sortedArrayUsingDescriptors:@[sortDescriptor]];
localizedStandardCompare: 會智能識別數字字串並按數值大小排序,支援本地化數字格式。
// 數據獲取階段轉換
for (NSDictionary *dict in originalArray) {
NSString *priceStr = dict[@"Price"];
if (priceStr) {
dict[@"PriceNumber"] = @([priceStr doubleValue]); // 添加數值字段
}
}
// 排序時使用數值字段
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"PriceNumber" ascending:YES];
NSArray *sorted = [array sortedArrayUsingDescriptors:@[sort]];
NSArray *sorted = [symbolArray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *price1 = obj1[@"Price"];
NSString *price2 = obj2[@"Price"];
if (!price1 && !price2) return NSOrderedSame;
if (!price1) return NSOrderedDescending; // nil 排最後
if (!price2) return NSOrderedAscending;
double d1 = [price1 doubleValue];
double d2 = [price2 doubleValue];
if (d1 < d2) return NSOrderedAscending;
if (d1 > d2) return NSOrderedDescending;
return NSOrderedSame;
}];
// 先按價格升序,價格相同再按成交量降序
NSSortDescriptor *priceSort = [[NSSortDescriptor alloc]
initWithKey:@"PriceNumber" ascending:YES];
NSSortDescriptor *volumeSort = [[NSSortDescriptor alloc]
initWithKey:@"VolumeNumber" ascending:NO];
NSArray *sorted = [array sortedArrayUsingDescriptors:@[priceSort, volumeSort]];
| 方法 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| localizedStandardCompare: | 字串數字、本地化格式 | 無需預處理、自動處理 | 大數據量較慢 |
| 轉 NSNumber 預處理 | 大量數據、頻繁排序 | 性能最好、類型安全 | 需額外內存、數據獲取時處理 |
| Comparator 塊 | 複雜邏輯、多條件 | 完全可控、可處理 nil | 代碼較長 |
let sorted = symbolArray.sorted { dict1, dict2 in
let price1 = (dict1["Price"] as? NSString)?.doubleValue ?? 0
let price2 = (dict2["Price"] as? NSString)?.doubleValue ?? 0
return price1 < price2
}
// 或使用 sortDescriptor
let descriptor = NSSortDescriptor(key: "Price", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:)))
let sorted = (symbolArray as NSArray).sortedArray(using: [descriptor])