1

我有以下问题:我有一个整数数组,我想把它们放在一个数据结构中,每个整数都有它的出现次数,然后按出现次数排序。

所以如果我有:

[1, 3, 4, 6, 6, 3, 1, 3]

我会有:

[(4,1), (6,2), (1,2), (3,3)]

其中 (x,y) == (整数,出现次数)。

我尝试使用 NSCountedSet 但效果不佳,我想知道最好的方法是什么。

到目前为止,我已经完成了以下工作:

NSCountedSet *totalSet = [[NSCountedSet alloc] initWithArray:finalArray];

其中 finalArray 是未排序的完整原始数据的最终数组。totalSet 分组为 (x,y) 但未排序(理想情况下,应按“y”排序)。

我也尝试过这样做,但没有奏效:

NSArray *sortedArray = [finalArray sortedArrayUsingSelector:@selector(compare:)];

然后做:

NSCountedSet *totalSet = [[NSCountedSet alloc] initWithArray:finalArray];

但这并没有改变“totalSet”。

4

3 回答 3

4

首先,让我们定义一个方便的元组类型,我们可以使用它来将一个数字与其出现次数相关联:

@interface Pair : NSObject
@property(nonatomic, strong) id key;
@property(nonatomic, strong) id value;
- (id)initWithKey:(id)key value:(id)value;
@end

@implementation Pair
- (id)initWithKey:(id)key value:(id)value;
{
    if((self = [super init])) {
        _key = key;
        _value = value;
    }
    return self;
}
- (NSString *)description
{
    return [NSString stringWithFormat:@"(%@,%@)", self.key, self.value];
}
@end

然后,为了获得所需的结果,使用计数集来计算出现次数,然后将结果填充到元组数组中并按出现次数排序。

- (void)testOccurrenceCounting
{
    NSArray *numbers = @[@1, @3, @4, @6, @6, @3, @1, @3];
    NSCountedSet *set = [[NSCountedSet alloc] initWithArray:numbers];
    NSMutableArray *counters = [NSMutableArray arrayWithCapacity:[set count]];
    [set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
        [counters addObject:[[Pair alloc] initWithKey:obj value:@([set countForObject:obj])]];
    }];
    [counters sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"value" ascending:YES]]];

    NSLog(@"%@", counters);
}

counters现在是一个排序的Pair对象数组,其中key属性保存数字,value属性保存出现次数,两者都装箱为NSNumbers. 从那里,您可以将它们拆箱或按您认为合适的方式操作集合。

作为有效的证明,下面是NSLog语句的输出:

(
    "(4,1)",
    "(6,2)",
    "(1,2)",
    "(3,3)"
)
于 2012-12-14T04:59:05.913 回答
3

您可以将数字及其计数放入字典数组中,如下所示:

    NSArray *arr = @[@1, @3, @4, @6, @6, @3, @1, @3];
    NSCountedSet *totalSet = [NSCountedSet setWithArray:arr];
    NSMutableArray *dictArray = [NSMutableArray array];
    for (NSNumber *num in totalSet) {
        NSDictionary *dict = @{@"number":num, @"count":@([totalSet countForObject:num])};
        [dictArray addObject:dict];
    }
    NSArray *final = [dictArray sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"number" ascending:YES ]]];
    NSLog(@"%@",final);
于 2012-12-14T06:03:17.407 回答
2

这是我的答案版本。如果您不想使用自定义类并希望将两者作为单独的数组按其出现次数的顺序排序,您可以试试这个。

创建一个这样的函数,

NSInteger countedSort(id obj1, id obj2, void *context) {
    NSCountedSet *countedSet = (__bridge NSCountedSet *)(context);
    NSUInteger obj1Count = [countedSet countForObject:obj1];
    NSUInteger obj2Count = [countedSet countForObject:obj2];

    if (obj1Count < obj2Count) return NSOrderedAscending;
    else if (obj1Count > obj2Count) return NSOrderedDescending;
    return NSOrderedSame;
}

并使用这个,

    NSArray *finalArray = @[@1, @3, @4, @6, @6, @3, @1, @3];    
    NSCountedSet *totalSet = [[NSCountedSet alloc] initWithArray:finalArray];
    NSArray *sortedBasedOnCountArray = [[totalSet allObjects] sortedArrayUsingFunction:countedSort context:(__bridge void *)(totalSet)];
    NSLog(@"sortedObjectsBasedOnCountArray = %@", sortedBasedOnCountArray);

    NSMutableArray *countArray = [NSMutableArray arrayWithCapacity:[sortedBasedOnCountArray count]];

    for (id object in sortedBasedOnCountArray) {
        [countArray addObject:[NSNumber numberWithInt:[totalSet countForObject:object]]];
    }
    NSLog(@"countArray = %@", countArray);

输出:

sortedObjectsBasedOnCountArray = (
    4,
    6,
    1,
    3
)

countArray = (
    1,
    2,
    2,
    3
)

请注意,两个数组都以相同的顺序排序,并且可以使用数组的索引来链接它们。

还要检查这个NSBag实现。

于 2012-12-14T05:26:11.513 回答