2012-11-20 53 views
6

我有兩個NSArray對象,我希望排序相同。一個包含NSString對象,另一個自定義Attribute對象。這是我的「鑰匙」的NSArray的樣子:根據另一個字符串NSArray的排序對自定義對象排序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陣列,以確定的排序定製對象數組。 我該怎麼做?

+0

這似乎並不像使用數組的好地方。字典或有序字典可能更合適,也更容易。 – Alexander

回答

13

在此,我與obj2.assetID在stringOrder索引比較obj1.assetID的直接指數stringOrder(使用目標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]]] 
}]; 
+0

我只是得到一個「不可見@interface爲NSArray聲明選擇器sortUsingComparator:」當這樣做。 –

+0

它適用於10.6+或iOS 4.0+。您是否在尋找更多兼容解決方案? (void)sortUsingComparator:(NSComparator)cmptr NS_AVAILABLE(10_6,4_0); – cwehrung

+0

你確定「items」是否真的被聲明爲一個NSMutableArray(而不僅僅是一個NSArray)? – cwehrung

2

有幾種方法你可以採取。

您可以將您的Attribute對象存儲在NSDictionary中,其中的鍵是stringOrder數組中的字符串。然後,你可以拿到鑰匙的排序陣列,並用它來填充你使用,以顯示他們的任何觀點:

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

另一種是先進行排序順序的屬性對象的固有屬性,所以可以直接對一組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]]; 

比較

下面是結果形成上運行的兩種方法一個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

第二個排序結果與排序計數不同,因爲該對象不在sortby中 – ssj