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);
}

countersPairオブジェクトのソートされた配列に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 に答える