उद्देश्य-सी में डुप्लिकेट मान ( NSString) को हटाने का सबसे अच्छा तरीका NSMutableArray?
क्या इसे करने का सबसे आसान और सही तरीका है?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
उद्देश्य-सी में डुप्लिकेट मान ( NSString) को हटाने का सबसे अच्छा तरीका NSMutableArray?
क्या इसे करने का सबसे आसान और सही तरीका है?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
जवाबों:
आपका NSSetदृष्टिकोण सबसे अच्छा है यदि आप वस्तुओं के आदेश के बारे में चिंतित नहीं हैं, लेकिन फिर से, यदि आप आदेश के बारे में चिंतित नहीं हैं, तो आप उन्हें NSSetशुरू करने के लिए क्यों नहीं संग्रहीत कर रहे हैं ?
मैंने 2009 में नीचे उत्तर लिखा था; 2011 में, Apple ने NSOrderedSetiOS 5 और Mac OS X 10.7 में जोड़ा । एल्गोरिथ्म क्या था अब कोड की दो लाइनें हैं:
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
यदि आप आदेश के बारे में चिंतित हैं और आप iOS 4 या उससे पहले के संस्करण पर चल रहे हैं, तो सरणी की एक प्रति पर लूप करें:
NSArray *copy = [mutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[mutableArray removeObjectAtIndex:index];
}
index--;
}
[copy release];
[NSOrderedSet orderedSetWithArray:array];आप पहले के बजाय एक सरणी के माध्यम से वापस प्राप्त कर सकते हैं array = [orderedSet allObjects];या केवल NSOrderedSetएस का उपयोग कर सकते हैं NSArray।
[orderedSet allObjects]साथ बदलने की जरूरत है [orderedSet array]!
NSArrayऔर अस्थायी बनाना चाहिए NSMutableArray। अपने उदाहरण में आप इसके विपरीत काम करते हैं
NSSet) या @Simon Whitaker लिंक है जो डुप्लिकेट मान को जोड़ने से पहले रोकता है जो कुशल तरीका है?
मुझे पता है कि यह एक पुराना सवाल है, लेकिन NSArray यदि आप ऑर्डर के बारे में परवाह नहीं करते हैं, तो डुप्लिकेट को हटाने का एक और सुंदर तरीका है ।
यदि हम कुंजी संचालक कोडिंग से ऑब्जेक्ट ऑपरेटर्स का उपयोग करते हैं तो हम यह कर सकते हैं:
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
जैसा कि एंथोपक ने भी उल्लेख किया है कि संपत्ति के आधार पर डुप्लिकेट को निकालना संभव है। एक उदाहरण होगा:@distinctUnionOfObjects.name
@distinctUnionOfObjects.propertyकस्टम ऑब्जेक्ट्स की एक सरणी की संपत्ति द्वारा डुप्लिकेट को निकालने के लिए भी किया जा सकता है । उदाहरण के लिए@distinctUnionOfObjects.name
हां, NSSet का उपयोग करना एक समझदार दृष्टिकोण है।
जिम पल्स के जवाब में जोड़ने के लिए, यहां ऑर्डर को बनाए रखते हुए डुप्लिकेट को अलग करने का एक वैकल्पिक तरीका है:
// Initialise a new, empty mutable array
NSMutableArray *unique = [NSMutableArray array];
for (id obj in originalArray) {
if (![unique containsObject:obj]) {
[unique addObject:obj];
}
}
यह मूल रूप से जिम के रूप में एक ही दृष्टिकोण है, लेकिन मूल से डुप्लिकेट को हटाने के बजाय एक ताजा म्यूटेबल सरणी में अद्वितीय वस्तुओं को कॉपी करता है। यह एक बहुत बड़ी सरणी के मामले में कुछ डुप्लिकेट के साथ बहुत अधिक स्मृति को कुशल बनाता है (संपूर्ण सरणी की प्रतिलिपि बनाने की कोई आवश्यकता नहीं है), और मेरी राय में थोड़ा अधिक पठनीय है।
ध्यान दें कि किसी भी मामले में, यह देखने के लिए कि क्या कोई वस्तु पहले से ही लक्ष्य सरणी में शामिल है ( containsObject:मेरे उदाहरण में, या indexOfObject:inRange:जिम में) बड़े सरणियों के लिए अच्छी तरह से स्केल नहीं करता है। वे चेक ओ (एन) समय में चलते हैं, जिसका अर्थ है कि यदि आप मूल सरणी के आकार को दोगुना करते हैं तो प्रत्येक चेक को चलने में दोगुना समय लगेगा। जब से आप सरणी में प्रत्येक ऑब्जेक्ट के लिए चेक कर रहे हैं, तो आप उन अधिक महंगी चेक को भी चला रहे होंगे। समग्र एल्गोरिथ्म (मेरा और जिम दोनों) ओ (एन 2 ) समय में चलता है , जो मूल सरणी बढ़ने के साथ जल्दी महंगा हो जाता है।
उस डाउन टू ओ (एन) समय को प्राप्त करने के लिए आप NSMutableSetनए एरे में पहले से जोड़े गए आइटमों के रिकॉर्ड को स्टोर करने के लिए उपयोग कर सकते हैं , क्योंकि एनएसएसईटी लुकअप ओ (एन) के बजाय ओ (1) हैं। दूसरे शब्दों में, यह देखने के लिए कि क्या कोई तत्व NSSet का सदस्य है, सेट में कितने तत्व हैं, इसकी परवाह किए बिना एक ही समय लगता है।
इस दृष्टिकोण का उपयोग कर कोड कुछ इस तरह दिखाई देगा:
NSMutableArray *unique = [NSMutableArray array];
NSMutableSet *seen = [NSMutableSet set];
for (id obj in originalArray) {
if (![seen containsObject:obj]) {
[unique addObject:obj];
[seen addObject:obj];
}
}
यह अभी भी थोड़ा बेकार लगता है; हम अभी भी एक नई व्यूह रचना कर रहे हैं, जब प्रश्न स्पष्ट हो गया है कि मूल सारणी उत्परिवर्तनीय है, इसलिए हमें इसे जगह पर डी-डुबाने में सक्षम होना चाहिए और कुछ मेमोरी को सहेजना चाहिए। कुछ इस तरह:
NSMutableSet *seen = [NSMutableSet set];
NSUInteger i = 0;
while (i < [originalArray count]) {
id obj = [originalArray objectAtIndex:i];
if ([seen containsObject:obj]) {
[originalArray removeObjectAtIndex:i];
// NB: we *don't* increment i here; since
// we've removed the object previously at
// index i, [originalArray objectAtIndex:i]
// now points to the next object in the array.
} else {
[seen addObject:obj];
i++;
}
}
अद्यतन : यूरी नियाज़ोव ने बताया कि मेरा अंतिम उत्तर वास्तव में ओ (एन 2 ) removeObjectAtIndex:में चलता है क्योंकि शायद ओ (एन) समय में चलता है।
(वे कहते हैं "शायद" क्योंकि हम यह सुनिश्चित करने के लिए नहीं जानते हैं कि यह कैसे लागू किया जाता है, लेकिन एक संभव कार्यान्वयन यह है कि ऑब्जेक्ट को इंडेक्स एक्स पर हटाने के बाद विधि फिर एरे में एक्स + 1 से आखिरी ऑब्जेक्ट तक हर तत्व से गुजरती है। , उन्हें पिछले सूचकांक में ले जाना। यदि ऐसा है तो वास्तव में O (N) प्रदर्शन है।)
इसलिए क्या करना है? यह स्थिति पर निर्भर करता है। यदि आपको एक बड़ा सरणी मिला है और आप केवल बहुत सारे डुप्लिकेट की उम्मीद कर रहे हैं तो इन-प्लेस डे-डुप्लीकेशन ठीक काम करेगा और आपको डुप्लिकेट सरणी बनाने के लिए बचाएगा। यदि आपको एक ऐसा सरणी मिला है जहाँ आप बहुत सारे डुप्लिकेट की उम्मीद कर रहे हैं तो एक अलग, डी-डुप्ड सरणी का निर्माण करना संभवतः सबसे अच्छा तरीका है। यहाँ ले दूर यह है कि बड़ा- O अंकन केवल एक एल्गोरिथ्म की विशेषताओं का वर्णन करता है, यह आपको निश्चित रूप से नहीं बताएगा जो किसी भी परिस्थिति के लिए सबसे अच्छा है।
यदि आप iOS 5+ (संपूर्ण iOS दुनिया को कवर करता है) को लक्षित कर रहे हैं, तो सबसे अच्छा उपयोग करें NSOrderedSet। यह डुप्लिकेट को हटाता है और आपके आदेश को बनाए रखता है NSArray।
बस करो
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
अब आप इसे एक अद्वितीय NSArray में बदल सकते हैं
NSArray *uniqueArray = orderedSet.array;
या सिर्फ ऑर्डरसेट का उपयोग करें क्योंकि इसमें NSArray की तरह ही तरीके हैं objectAtIndex:, firstObjectऔर इसी तरह।
जिस containsपर NSOrderedSetयह होगा उस पर सदस्यता की जांच और भी तेज हैNSArray
अधिक चेकआउट के लिए NSOrderedSet Reference
OS X v10.7 और बाद में उपलब्ध है।
यदि आप आदेश के बारे में चिंतित हैं, तो करने का सही तरीका
NSArray *no = [[NSOrderedSet orderedSetWithArray:originalArray]allObjects];
यहाँ आदेश में NSArray से डुप्लिकेट मानों को हटाने का कोड है।
आदेश की आवश्यकता है
NSArray *yourarray = @[@"a",@"b",@"c"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourarray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
NSLog(@"%@",arrayWithoutDuplicates);
या आदेश की जरूरत नहीं है
NSSet *set = [NSSet setWithArray:yourarray];
NSArray *arrayWithoutOrder = [set allObjects];
NSLog(@"%@",arrayWithoutOrder);
यहाँ मैंने मुख्य नाम से डुप्लिकेट नाम मान हटा दिए और NSMutableArray (listOfUsers) में स्टोर परिणाम
for (int i=0; i<mainArray.count; i++) {
if (listOfUsers.count==0) {
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
else if ([[listOfUsers valueForKey:@"name" ] containsObject:[[mainArray objectAtIndex:i] valueForKey:@"name"]])
{
NSLog(@"Same object");
}
else
{
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
}
ध्यान दें कि यदि आपके पास एक सॉर्ट किया गया सरणी है, तो आपको सरणी में हर अंतिम आइटम के खिलाफ जांचने की आवश्यकता नहीं है, बस अंतिम आइटम। यह सभी वस्तुओं के खिलाफ जाँच करने की तुलना में बहुत तेज़ होना चाहिए।
// sortedSourceArray is the source array, already sorted
NSMutableArray *newArray = [[NSMutableArray alloc] initWithObjects:[sortedSourceArray objectAtIndex:0]];
for (int i = 1; i < [sortedSourceArray count]; i++)
{
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
{
[newArray addObject:[tempArray objectAtIndex:i]];
}
}
यह उन NSOrderedSetउत्तरों की तरह दिखता है जिनके सुझाव भी बहुत कम कोड की आवश्यकता होती है, लेकिन यदि आप NSOrderedSetकिसी कारण से उपयोग नहीं कर सकते हैं , और आपके पास एक क्रमबद्ध सरणी है, तो मुझे विश्वास है कि मेरा समाधान सबसे तेज़ होगा। मुझे यकीन नहीं है कि यह कैसे NSOrderedSetसमाधान की गति के साथ तुलना करता है। यह भी ध्यान दें कि मेरा कोड के साथ जाँच कर रहा है isEqualToString:, इसलिए अक्षरों की एक ही श्रृंखला एक से अधिक बार दिखाई नहीं देगी newArray। मुझे यकीन नहीं है कि NSOrderedSetसमाधान मूल्य के आधार पर या स्मृति स्थान के आधार पर डुप्लिकेट को हटा देगा।
मेरा उदाहरण मानता है कि sortedSourceArrayसिर्फ NSStringएस, सिर्फ NSMutableStringएस या दोनों का मिश्रण है। अगर sortedSourceArrayइसके बजाय सिर्फ NSNumbers या सिर्फ NSDates है, तो आप प्रतिस्थापित कर सकते हैं
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
साथ में
if ([[sortedSourceArray objectAtIndex:i] compare:[sortedSourceArray objectAtIndex:(i-1)]] != NSOrderedSame)
और इसे पूरी तरह से काम करना चाहिए। यदि sortedSourceArrayइसमें NSStrings, NSNumbers और / या NSDates का मिश्रण है, तो यह संभवतः दुर्घटनाग्रस्त हो जाएगा।
एक केवीसी ऑब्जेक्ट ऑपरेटर है जो एक अधिक सुरुचिपूर्ण समाधान प्रदान करता है uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];यहां एक एनएसएरे श्रेणी है ।
एक और सरल तरीका है जिसे आप आज़मा सकते हैं, जो सरणी में ऑब्जेक्ट जोड़ने से पहले डुप्लिकेट मान नहीं जोड़ेंगे: -
// मान लें कि mutableArray आवंटित किया गया है और प्रारंभिक है और इसमें कुछ मूल्य हैं
if (![yourMutableArray containsObject:someValue])
{
[yourMutableArray addObject:someValue];
}
उद्देश्य-सी में NSMutableArray से डुप्लिकेट मान निकालें
NSMutableArray *datelistArray = [[NSMutableArray alloc]init];
for (Student * data in fetchStudentDateArray)
{
if([datelistArray indexOfObject:data.date] == NSNotFound)
[datelistArray addObject:data.date];
}
यहाँ NSMutable Array से डुप्लिकेट मानों को हटाने का कोड है। यह आपके लिए काम करेगा। myArray आपका Mutable Array है जिसे आप डुप्लिकेट मानों को हटाना चाहते हैं।
for(int j = 0; j < [myMutableArray count]; j++){
for( k = j+1;k < [myMutableArray count];k++){
NSString *str1 = [myMutableArray objectAtIndex:j];
NSString *str2 = [myMutableArray objectAtIndex:k];
if([str1 isEqualToString:str2])
[myMutableArray removeObjectAtIndex:k];
}
} // Now print your array and will see there is no repeated value
बस इस सरल कोड का उपयोग करें:
NSArray *hasDuplicates = /* (...) */;
NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects];
चूंकि nsset डुप्लिकेट मानों की अनुमति नहीं देता है और सभी ऑब्जेक्ट एक सरणी देता है
NSOrderedSetकी insteed NSSet।