2012-11-20 40 views
6

NSArray ऑब्जेक्ट्स के दो एनएसएआरएआरई को सॉर्ट करने के आधार पर कस्टम ऑब्जेक्ट्स के एनएसएआरएआर को सॉर्ट करें, मेरे पास दो सॉर्ट्स हैं जिन्हें मैं सॉर्ट करना चाहता हूं। एक में NSString ऑब्जेक्ट्स, अन्य कस्टम Attribute ऑब्जेक्ट्स शामिल हैं।स्ट्रिंग्स

// 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

इसके द्वारा, मैं stringOrder में obj2.assetID के सूचकांक के साथ stringOrder में सीधे obj1.assetID के सूचकांक की तुलना (@ के लिए ऑब्जेक्टिव-सी शाब्दिक का उपयोग कर() 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

मुझे बस "एनएसएआरएआरई के लिए कोई दृश्यमान @ इंटरफेस नहीं मिलता है चयनकर्ता सॉर्ट यूजिंग कॉम्परेटर:" ऐसा करने पर। –

+0

यह 10.6+ या आईओएस 4.0+ के साथ उपलब्ध है। क्या आप अधिक संगत समाधान ढूंढ रहे हैं? - (शून्य) sortUsingComparator: (NSComparator) cmptr NS_AVAILABLE (10_6, 4_0); – cwehrung

+0

क्या आप वाकई "आइटम" को एनएसएमयूटेबलएरे के रूप में घोषित करते हैं (और न केवल एक एनएसएआरएआरई)? – cwehrung

2

कुछ दृष्टिकोण हैं जो आप ले सकते हैं।

आप अपनी स्ट्रिंग ऑर्डर में स्ट्रिंग होने वाली कुंजी के साथ, एनएस डिक्शनरी में अपनी विशेषता ऑब्जेक्ट्स स्टोर कर सकते हैं। उसके बाद, आप चाबियों का एक क्रमबद्ध सरणी मिलता है और उपयोग करने वाले को भरने के लिए जो कुछ भी दृश्य आप उन्हें प्रदर्शित करने के लिए प्रयोग कर रहे हैं हो सकता है:

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

अन्य है कि आप सॉर्ट क्रम अपने गुण वस्तु का एक आंतरिक संपत्ति कर है, तो गुणों की एक सरणी सीधे क्रमबद्ध किया जा सकता है। अगर सॉर्ट ऑर्डर वास्तव में आपके गुण ऑब्जेक्ट्स की आंतरिक संपत्ति है तो मैं केवल इस दृष्टिकोण को लेने की अनुशंसा करता हूं। यदि यह नहीं है और आप ऐसा करते हैं, तो आप प्रस्तुतिकरण जानकारी संग्रहीत कर देंगे जहां यह संबंधित नहीं है।

यहाँ एक उदाहरण है:

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

तो आपके पहले उदाहरण में, शब्दकोश को मेरी ऑब्जेक्ट की परिसंपत्ति आईडी के आधार पर सॉर्ट करना कैसे पता चलेगा? –

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

में इंडेक्स से अपने इंडेक्स में एक शब्दकोश बनाने से भी बेहतर होंगे, दूसरा क्रमबद्ध परिणाम सॉर्टमे गिनती से भिन्न होता है क्योंकि ऑब्जेक्ट सॉर्टबाय में नहीं था – ssj

संबंधित मुद्दे