7

NSArray同じように並べ替えたいオブジェクトが 2 つあります。1 つはNSStringオブジェクトを含み、もう 1 つはカスタムAttributeオブジェクトを含みます。これが私の「キー」NSArrayの外観です。

// The master order
NSArray *stringOrder = [NSArray arrayWithObjects:@"12", @"10", @"2", nil];

カスタム オブジェクトを含む NSArray:

// The array of custom Attribute objects that I want sorted by the stringOrder array
NSMutableArray *items = [[NSMutableArray alloc] init];
Attribute *attribute = nil;

attribute = [[Attribute alloc] init];
attribute.assetID = @"10";
[items addObject:attribute];

attribute = [[Attribute alloc] init];
attribute.assetID = @"12";
[items addObject:attribute];

attribute = [[Attribute alloc] init];
attribute.assetID = @"2";
[items addObject:attribute];

したがって、私がやりたいことは、配列を使用してカスタム オブジェクトstringOrderの配列の並べ替えを決定することです。itemsこれどうやってするの?

4

5 に答える 5

14

ここで、stringOrder の obj1.assetID のインデックスと stringOrder の obj2.assetID のインデックスを直接比較します (@() の Objective-C リテラルを使用して NSString => NSNumber を変換します)。

[items sortUsingComparator:^NSComparisonResult(Attribute *obj1, Attribute *obj2) {
    return [@([stringOrder indexOfObject:obj1.assetID]) compare:@([stringOrder indexOfObject:obj2.assetID])]
}];

または ObjC リテラルなし:

[items sortUsingComparator:^NSComparisonResult(Attribute *obj1, Attribute *obj2) {
    return [[NSNumber numberWithInt:[stringOrder indexOfObject:obj1.assetID]] compare:[NSNumber numberWithInt:[stringOrder indexOfObject:obj2.assetID]]]
}];
于 2012-11-20T16:56:32.787 に答える
6

cwehrungs の回答で仕事は完了しますが、比較的小さなアレイではパフォーマンスが良くありません。

同じ種類の並べ替えを実行する別の方法を次に示します。

NSMutableArray *sorted = [NSMutableArray array];

// pre-populate with objects
for (int i = 0; i < stringOrder.count; i++)
{
    [sorted addObject:[NSNull null]];
}
// place the items at the correct position
for (Attribute *a in items)
{
    NSUInteger idx = [stringOrder indexOfObject:a.assetID];
    if (idx != NSNotFound)
    {
        [sorted setObject:a atIndexedSubscript:idx];
    }
}
// finally remove all the unecesarry placeholders if one array was smaller
[sorted removeObject:[NSNull null]];

比較

iPhone 5 で 2 つのメソッドを実行した結果のフォームを次に示します。

sortUsingComparator:

100  - 0.012 s
1000 - 1.116 s
2000 - 4.405 s
3000 - 9.028 s

事前設定された配列

100 -  0.003 s
1000 - 0.236 s
2000 - 0.917 s
3000 - 2.063 s
于 2014-10-31T16:26:40.237 に答える
2

いくつかの方法があります。

Attribute オブジェクトを NSDictionary に格納し、キーを stringOrder 配列の文字列にすることができます。次に、キーの並べ替えられた配列を取得し、それを使用して、それらを表示するために使用しているビューを設定できます。

NSArray* sortedKeys = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) {
    return [obj1 compareTo:obj2];
}

もう 1 つは、並べ替え順序を Attribute オブジェクトの組み込みプロパティにすることです。これにより、Attribute の配列を直接並べ替えることができます。並べ替え順序が実際に Attributes オブジェクトの固有のプロパティである場合にのみ、このアプローチを取ることをお勧めします。そうでない場合にこれを行うと、プレゼンテーション情報が属していない場所に保存されることになります。

次に例を示します。

NSArray* sortedAttrs = [attributes sortedArrayUsingComparator:^(id obj1, id obj2) {
    // Perform comparison of Attribute's, ahem, attributes
}
于 2012-11-20T09:09:45.937 に答える
0

並列処理:

結果 (クアッドコア):

 1. sortme:95    sortby:852345 sorted:95    time:0.052576
 2. sortme:54248 sortby:852345 sorted:54243 time:0.264660





-(NSArray *)sortArray:(NSArray *)sortme sortBy:(NSArray *)sortBy{

CFAbsoluteTime time = CFAbsoluteTimeGetCurrent();

NSSet *sortmeSet = [NSSet setWithArray:sortme];

NSMutableDictionary *sortDictionary = [NSMutableDictionary dictionary];
dispatch_queue_t sortDictionaryThread = dispatch_queue_create("my.sortDictionaryThread", DISPATCH_QUEUE_CONCURRENT);

[sortBy enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

    if ([sortmeSet containsObject:obj]){
        dispatch_barrier_async(sortDictionaryThread, ^{
            sortDictionary[obj] = @(idx);
        });
    }
}];


__block NSArray *sortedArray = nil;
dispatch_barrier_sync(sortDictionaryThread, ^{
    sortedArray = [sortDictionary keysSortedByValueUsingSelector:@selector(compare:)];
});

NSLog(@"sortme:%li sortby:%li sorted:%li time:%f",sortme.count,sortBy.count,sortedArray.count, CFAbsoluteTimeGetCurrent() - time);

return sortedArray;
}
于 2016-05-05T17:22:45.803 に答える