2012-11-20 8 views
6

私は2つのNSArrayのオブジェクトを並べ替えたいと思います。 1つはNSStringオブジェクト、もう1つはカスタムAttributeオブジェクトです。カスタムオブジェクトと文字列の別のNSArrayのソートに基づいてカスタムオブジェクトのNSArrayを並べ替えます。

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

にNSArray:ここに私は、「キー」は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カスタムオブジェクトの配列。 どうすればいいですか?

+0

これは、配列を使用するためには良い場所のように見えるしていません。辞書や順序付けされた辞書がより適切で簡単になるかもしれません。 – Alexander

答えて

13

これにより、私は(NSStringの=>のNSNumberを形質転換するために)(@ためのObjective-Cリテラルを使用して)stringOrderにおけるobj2.assetIDの指標と直接stringOrderでobj1.assetIDのインデックスを比較

[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]]] 
}]; 
+0

これを実行すると、NSArrayがセレクタsortUsingComparator:を宣言するための "表示されない@interface"が表示されます。 –

+0

10.6+またはiOS 4.0+で利用できます。より互換性のあるソリューションをお探しですか? - (void)sortUsingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6、4_0); – cwehrung

+0

"items"は実際にはNSMutableArray(NSArrayだけでなく)として宣言されていますか? – cwehrung

2

いくつかのアプローチがあります。

キーを文字列の配列であるNSDictionaryに格納することができます。その後、あなたは、キーのソートされた配列を取得し、あなたがそれらを表示するために使用しているものは何でもビュー移入することを使用することができます。

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

他のあなたはソート順、あなたの属性オブジェクトの固有の特性にすることです、 Attributesの配列を直接ソートすることができます。ソート順が実際にあなたのAttributesオブジェクトの本質的なプロパティである場合にのみ、このアプローチをとることをお勧めします。そうでなければ、あなたはそれが属していないプレゼンテーション情報を保存してしまいます。ここで

は例です:

NSArray* sortedAttrs = [attributes sortedArrayUsingComparator:^(id obj1, id obj2) { 
    // Perform comparison of Attribute's, ahem, attributes 
} 
+0

あなたの最初の例では、辞書は自分のオブジェクトのassetIDプロパティに基づいてソートする方法をどのように知っていますか? –

1

ここで私はそれが非常にうまく機能を思い付いたソリューションです。誰もがこれにパフォーマンスの問題を参照してください?

for (Attribute *a in items) { 
    int index = [stringOrder indexOfObject:a.assetID]; 
    a.sortOrder = index; 
} 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sortOrder" ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 
NSArray *sortedArray = [items sortedArrayUsingDescriptors:sortDescriptors]; 
5

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]]; 

比較

ここでの結果は、上の2つのメソッドを実行して形成されていますiPhone 5:

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 
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; 
} 
+0

2番目のソート結果は、オブジェクトがソートバイではなかったためsortmeカウントとは異なります – ssj

関連する問題