在 iOS 中統計數組中各元素出現次數,使用 NSCountedSet(計數集合)是最高效、代碼最簡潔的方案,避免手動遍歷字典計數。
NSMutableArray *array = [@[@1, @2, @3, @3, @2, @1, @6, @2] mutableCopy];
// 期望輸出:1=2, 2=3, 3=2, 6=1
// 1. 創建計數集合
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
// 2. 遍歷輸出統計結果
for (NSNumber *number in countedSet) {
NSUInteger count = [countedSet countForObject:number];
NSLog(@"%@ = %lu", number, (unsigned long)count);
}
// 輸出:
// 1 = 2
// 2 = 3
// 3 = 2
// 6 = 1
NSMutableSet,元素唯一(集合特性)countForObject: 返回元素添加次數addObject: 增加計數,removeObject: 減少計數// 低效手動實現
NSMutableDictionary *countDict = [NSMutableDictionary dictionary];
for (id obj in array) {
NSNumber *count = countDict[obj];
countDict[obj] = @(count.unsignedIntegerValue + 1);
}
// 代碼冗長、易出錯、性能略低
- (NSArray *)topKFrequentElements:(NSArray *)array k:(NSUInteger)k {
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
// 轉換為字典排序
NSMutableDictionary *freqDict = [NSMutableDictionary dictionary];
for (id obj in countedSet) {
freqDict[obj] = @([countedSet countForObject:obj]);
}
// 按計數降序排序
NSArray *sortedKeys = [freqDict keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj2 compare:obj1]; // 降序
}];
// 取前 K 個
NSUInteger limit = MIN(k, sortedKeys.count);
return [sortedKeys subarrayWithRange:NSMakeRange(0, limit)];
}
| 類型 | 是否支援 | 說明 |
|---|---|---|
| NSNumber / NSString | ✅ | 符合 NSCopying 協議 |
| 自定義對象 | ✅ (需實現) | 需實現 isEqual: 和 hash,並符合 NSCopying |
| 基本數據類型 (int, float) | ❌ | 需包裝為 NSNumber |
let array = [1, 2, 3, 3, 2, 1, 6, 2]
let countedSet = NSCountedSet(array: array)
for obj in countedSet {
let count = countedSet.count(for: obj)
print("\(obj) = \(count)")
}
// 或使用 Swift 原生
let frequencies = Dictionary(array.map { ($0, 1) }, uniquingKeysWith: +)
// frequencies: [2: 3, 3: 2, 1: 2, 6: 1]