दिलचस्प पोस्ट
एक चित्रबाक्स समस्या का उपयोग '? फैलता है 'और'? सुपर 'में संग्रह जेनरिक कॉर्डोवा + अंगुलरज + डिवाइस तैयार प्रमुख नाम में मोंगोडीबी डॉट (।) रूबी में सीटीवी में आउटपुट सरणी जेएसओएन से एक्सएमएल रूपांतरण के जावा कार्यान्वयन मैत्रीपूर्ण URL के लिए .php एक्सटेंशन (स्पष्ट रूप से लिखा हुआ) निकालें jquery form.serialize और अन्य पैरामीटर UICollectionView सेल गायब हो रहा है जावा में बराबर लम्बाई सबस्ट्रिंग को स्प्लिट स्ट्रिंग मैं एक ही आईडी के साथ सभी तत्वों के लिए jQuery फ़ंक्शन कैसे लागू करूं? मैट्रिक्स की पंक्तियों को सॉर्ट करने के लिए जोर कैसे उपयोग करें? मैं जावा में जावा का उपयोग कैसे कर सकता हूं? पाठ-ओवरफ्लो: फ़ायरफ़ॉक्स 4 में एलीप्सिस? (और एफएफ 5) LINQ का प्रयोग करके अल्फ़ान्यूमेरिक सॉर्टिंग

एनएसएमयूटीबलएआरआरआर से निकालने का सबसे अच्छा तरीका क्या है?

कोको में, अगर मैं एक NSMutableArray के माध्यम से लूप करना चाहता हूं और एक निश्चित मानदंड में फिट होने वाले कई ऑब्जेक्ट्स को निकालना चाहता हूं, तो हर बार मैं ऑब्जेक्ट निकालने के बाद पाश को दोबारा शुरू करने के बाद क्या करने का सबसे अच्छा तरीका है?

धन्यवाद,

संपादित करें: बस स्पष्ट करने के लिए – मैं सबसे अच्छे तरीके से तलाश कर रहा था, उदाहरण के लिए मैन्युअल रूप से मैन्युअल रूप से अपडेट करने की तुलना में कुछ अधिक सुंदर। उदाहरण के लिए सी ++ मैं कर सकता हूं;

iterator it = someList.begin(); while (it != someList.end()) { if (shouldRemove(it)) it = someList.erase(it); } 

वेब के समाधान से एकत्रित समाधान "एनएसएमयूटीबलएआरआरआर से निकालने का सबसे अच्छा तरीका क्या है?"

स्पष्टता के लिए मैं एक प्रारंभिक लूप बनाना चाहता हूं जहां मैं आइटम को हटाने के लिए जमा करता हूं। तब मैं उन्हें हटा देता हूं। यहाँ उद्देश्य-सी 2.0 वाक्यविन्यास का उपयोग कर एक नमूना है:

 NSMutableArray *discardedItems = [NSMutableArray array]; SomeObjectClass *item; for (item in originalArrayOfItems) { if ([item shouldBeDiscarded]) [discardedItems addObject:item]; } [originalArrayOfItems removeObjectsInArray:discardedItems]; 

इसके बाद कोई भी सवाल नहीं है कि क्या सूचकांक सही तरीके से अद्यतन किए जा रहे हैं या अन्य छोटे बहीखाता विवरण।

जोड़ने के लिए संपादित:

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

http://ridiculousfish.com/blog/archives/2005/12/23/array/

व्युत्क्रम तैयार हो सकता है, लेकिन मुझे यह ध्यान देने की आवश्यकता नहीं है कि यह क्या है, क्योंकि उपरोक्त तैयारियाँ हमेशा मेरी आवश्यकताओं के लिए तेज़ी से पर्याप्त रही हैं

मेरे लिए ले-होम संदेश का उपयोग करना है जो कुछ भी आपके लिए स्पष्ट है I केवल तभी आवश्यक है जब आवश्यक हो। मैं व्यक्तिगत तौर पर उपरोक्त फॉर्मूलेशन को स्पष्ट करता हूं, यही कारण है कि मैं इसका इस्तेमाल करता हूं। लेकिन अगर व्युत्क्रम तैयार करना आपके लिए स्पष्ट है, तो इसके लिए जाएं।

एक और बदलाव तो आपको पठनीयता और अच्छा प्रदर्शन मिलता है:

 NSMutableIndexSet *discardedItems = [NSMutableIndexSet indexSet]; SomeObjectClass *item; NSUInteger index = 0; for (item in originalArrayOfItems) { if ([item shouldBeDiscarded]) [discardedItems addIndex:index]; index++; } [originalArrayOfItems removeObjectsAtIndexes:discardedItems]; 

अन्य उत्तरों में से कुछ बहुत बड़े एरेज़ पर खराब प्रदर्शन करेंगे, क्योंकि removeObject: जैसे तरीकों removeObject: और removeObjectsInArray: रिसीवर की एक रैखिक खोज करना शामिल है, जो कचरा है क्योंकि आप पहले से जानते हैं कि ऑब्जेक्ट कहां है। साथ ही, removeObjectAtIndex: को removeObjectAtIndex: लिए कोई भी कॉल removeObjectAtIndex: को एक समय में एक स्लॉट द्वारा सरणी के अंत तक सूचकांक से मूल्यों को कॉपी करना होगा।

अधिक कुशल होगा निम्नलिखित:

 NSMutableArray *array = ... NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[array count]]; for (id object in array) { if (! shouldRemove(object)) { [itemsToKeep addObject:object]; } } [array setArray:itemsToKeep]; 

क्योंकि हम itemsToKeep की क्षमता को सेट करते हैं, हम एक आकार के दौरान मूल्यों को कॉपी करते समय कभी भी बर्बाद नहीं करते हैं। हम जगह में सरणी को संशोधित नहीं करते हैं, इसलिए हम फास्ट एन्यूमेशन का उपयोग करने के लिए स्वतंत्र हैं। setArray: का उपयोग करना setArray: साथ array की सामग्री को प्रतिस्थापित करने के लिए itemsToKeep कुशल हो जाएगा। आपके कोड के अनुसार, आप निम्न पंक्ति को इसके साथ भी बदल सकते हैं:

 [array release]; array = [itemsToKeep retain]; 

इसलिए मूल्यों की प्रतिलिपि बनाने की भी आवश्यकता नहीं है, केवल एक सूचक को स्वैप करें

रोना के लिए 'जोर से बाहर !! यह एक बहुत ही सरल समस्या है आप केवल पीछे की तरफ इशारा करते हैं:

 for (NSInteger i = array.count - 1; i >= 0; i--) { ElementType* element = array[i]; if ([element shouldBeRemoved]) { [array removeObjectAtIndex:i]; } } 

यह एक बहुत ही आम पैटर्न है, लेकिन केवल जेन्स ने इसे प्राप्त कर लिया है।

आप अपने अस्थिर सरणी से आइटम को निकालने के लिए एनएसपी्रेडिकेट का उपयोग कर सकते हैं। इसके लिए लूप की आवश्यकता नहीं है

उदाहरण के लिए यदि आपके पास नामों के एक NSMutableArray है, तो आप इस तरह एक predicate बना सकते हैं:

 NSPredicate *caseInsensitiveBNames = [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"]; 

निम्नलिखित पंक्ति आपको एक सरणी के साथ छोड़ देगी जिसमें केवल नाम से शुरू होने वाले नाम बी होते हैं।

 [namesArray filterUsingPredicate:caseInsensitiveBNames]; 

यदि आप की जरूरत है जो भविष्यवाणी बनाने में परेशानी है, इस सेब डेवलपर लिंक का उपयोग करें

या तो इंडेक्सों पर नीचे की गणना करने वाले लूप का उपयोग करें – (एनएसआईएनटीईजीआई = सरणी- count – 1; i> = 0; -i) के लिए- या उस ऑब्जेक्ट के साथ एक प्रति बनाओ जिसे आप रखना चाहते हैं। विशेष रूप से, किसी (id ऑब्जेक्ट में सरणी) लूप या NSEnumerator का उपयोग न करें।

मैंने 4 अलग-अलग तरीकों का इस्तेमाल करते हुए एक प्रदर्शन टेस्ट किया प्रत्येक परीक्षण 100,000 तत्व सरणी में सभी तत्वों के माध्यम से दोहराया जाता है, और हर 5 वीं मद को हटा दिया जाता है परिणामों के साथ अनुकूलन के बिना / अधिक भिन्नता नहीं थी यह एक iPad 4 पर किया गया था:

(1) removeObjectAtIndex:271 एमएस

(2) removeObjectsAtIndexes:1010 एमएस (क्योंकि सूचकांक सेट को बनाना ~ 700 एमएस लेता है, अन्यथा यह मूल रूप से केवल हटाने वाले ऑब्जेक्टआटइंडएक्स को कॉल करने के समान है: प्रत्येक आइटम के लिए)

(3) removeObjects:326 एमएस

(4) परीक्षा पास करने वाले वस्तुओं के साथ एक नई सरणी बनाओ – 17 एमएस

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

आईओएस 4+ या ओएस एक्स 10.6+ के लिए, ऐप्पल ने passingTest में एपीआई को जोड़ते हुए passingTest सीरीज को जोड़ा, जैसे – indexesOfObjectsPassingTest: । ऐसे एपीआई के साथ एक समाधान होगा:

 NSIndexSet *indexesToBeRemoved = [someList indexesOfObjectsPassingTest: ^BOOL(id obj, NSUInteger idx, BOOL *stop) { return [self shouldRemove:obj]; }]; [someList removeObjectsAtIndexes:indexesToBeRemoved]; 

आजकल आप बदले गए ब्लॉक-आधारित गणना का उपयोग कर सकते हैं एक सरल उदाहरण कोड:

 NSMutableArray *array = [@[@{@"name": @"a", @"shouldDelete": @(YES)}, @{@"name": @"b", @"shouldDelete": @(NO)}, @{@"name": @"c", @"shouldDelete": @(YES)}, @{@"name": @"d", @"shouldDelete": @(NO)}] mutableCopy]; [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if([obj[@"shouldDelete"] boolValue]) [array removeObjectAtIndex:idx]; }]; 

परिणाम:

 ( { name = b; shouldDelete = 0; }, { name = d; shouldDelete = 0; } ) 

सिर्फ एक पंक्ति कोड के साथ दूसरा विकल्प:

 [array filterUsingPredicate:[NSPredicate predicateWithFormat:@"shouldDelete == NO"]]; 

एक अधिक घोषणात्मक तरीके से, वस्तुओं से मेल खाने वाले मानदंडों के आधार पर आप उपयोग कर सकते हैं:

 [theArray filterUsingPredicate:aPredicate] 

@ नाथन बहुत कुशल होना चाहिए

यहाँ आसान और साफ रास्ता है मैं तेजी से गणना कॉल में मेरी सरणी को डुप्लिकेट करना चाहता हूं:

 for (LineItem *item in [NSArray arrayWithArray:self.lineItems]) { if ([item.toBeRemoved boolValue] == YES) { [self.lineItems removeObject:item]; } } 

इस तरह से आप सरणी की एक प्रति से हटाए जा रहे हैं, दोनों ही वस्तुओं को पकड़े हुए हैं। एक NSArray केवल ऑब्जेक्ट पॉइंटर्स रखता है इसलिए यह पूरी तरह से ठीक मेमोरी / प्रदर्शन बुद्धिमान है।

वे ऑब्जेक्ट जोड़ें जिन्हें आप एक दूसरे सरणी में निकालना चाहते हैं और, लूप के बाद, -removeObjectsInArray का उपयोग करें।

यह करना चाहिए:

  NSMutableArray* myArray = ....; int i; for(i=0; i<[myArray count]; i++) { id element = [myArray objectAtIndex:i]; if(element == ...) { [myArray removeObjectAtIndex:i]; i--; } } 

उम्मीद है की यह मदद करेगा…

आप अन्य NSMutableArray को हटाने के लिए ऑब्जेक्ट क्यों नहीं जोड़ते? जब आप दोबारा चलना समाप्त कर देते हैं, तो आप उन वस्तुओं को निकाल सकते हैं जिन्हें आपने एकत्र किया है।

यदि आपकी ऑरेम में सभी ऑब्जेक्ट अद्वितीय हैं या आप किसी ऑब्जेक्ट की सभी आवृत्तियों को निकालना चाहते हैं, तो आप मूल से ऑब्जेक्ट को निकालने के लिए एक सरणी प्रतिलिपि पर तेजी से एन्यूमरेट कर सकते हैं और [NSMutableArray removeObject:] का उपयोग कर सकते हैं।

 NSMutableArray *myArray; NSArray *myArrayCopy = [NSArray arrayWithArray:myArray]; for (NSObject *anObject in myArrayCopy) { if (shouldRemove(anObject)) { [myArray removeObject:anObject]; } } 

बेंजाडो के एन्वेस्टर ऊपर है जो आपको प्रीफोर्मोस के लिए करना चाहिए। मेरे एक आवेदन में हटाए गए ऑब्जेक्ट्स इनरेरे ने 1 मिनट का समय ले लिया, बस एक नई सरणी को जोड़कर .023 सेकंड

मैं उस श्रेणी को परिभाषित करता हूं जो मुझे एक ब्लॉक का उपयोग करके फ़िल्टर करता है, जैसे:

 @implementation NSMutableArray (Filtering) - (void)filterUsingTest:(BOOL (^)(id obj, NSUInteger idx))predicate { NSMutableIndexSet *indexesFailingTest = [[NSMutableIndexSet alloc] init]; NSUInteger index = 0; for (id object in self) { if (!predicate(object, index)) { [indexesFailingTest addIndex:index]; } ++index; } [self removeObjectsAtIndexes:indexesFailingTest]; [indexesFailingTest release]; } @end 

जो तब इस तरह इस्तेमाल किया जा सकता है:

 [myMutableArray filterUsingTest:^BOOL(id obj, NSUInteger idx) { return [self doIWantToKeepThisObject:obj atIndex:idx]; }]; 

NSMutableArray पर नीचे श्रेणी पद्धति का उपयोग करने के लिए एक अच्छा कार्यान्वयन हो सकता है।

 @implementation NSMutableArray(BMCommons) - (void)removeObjectsWithPredicate:(BOOL (^)(id obj))predicate { if (predicate != nil) { NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:self.count]; for (id obj in self) { BOOL shouldRemove = predicate(obj); if (!shouldRemove) { [newArray addObject:obj]; } } [self setArray:newArray]; } } @end 

सरणी में प्रत्येक ऑब्जेक्ट पर प्रसंस्करण करने के लिए विदग्ध ब्लॉक लागू किया जा सकता है। यदि विक्टिक रिटर्न सही होता है तो वस्तु हटा दी जाती है

अतीत में लिखे सभी तिथियों को निकालने के लिए दिनांक सारणी के लिए एक उदाहरण:

 NSMutableArray *dates = ...; [dates removeObjectsWithPredicate:^BOOL(id obj) { NSDate *date = (NSDate *)obj; return [date timeIntervalSinceNow] < 0; }]; 

तत्वों को स्वैप करने के बारे में, जिसे आप 'n'th तत्व,' n-1'th तत्व और इतने पर हटाना चाहते हैं?

जब आप कर लेंगे तो आप सरणी का आकार 'पिछले आकार में बदल सकते हैं – स्वैप की संख्या'

पीछे की तरफ उल्टा-सा मेरे लिए बहुत ही प्रिय था, लेकिन लंबे समय तक मुझे इस मामले का कभी सामना नहीं करना पड़ा जहां 'गहरातम' (उच्चतम गिनती) वस्तु पहले हटा दी गई थी। सूचक सूचकांक पर आगे बढ़ने से पहले कुछ भी नहीं है और यह क्रैश हो जाता है।

बेंजाडो का तरीका अब जो मैं करता हूं उसका सबसे निकटतम होता है, लेकिन मुझे कभी एहसास नहीं हुआ कि हर रिले के बाद स्टैक फेम फेले होगा।

Xcode 6 के तहत यह काम करता है

 NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[array count]]; for (id object in array) { if ( [object isNotEqualTo:@"whatever"]) { [itemsToKeep addObject:object ]; } } array = nil; array = [[NSMutableArray alloc]initWithArray:itemsToKeep];