অবজেক্টিভ-সি-তে NSMutableArray থেকে সদৃশ মানগুলি সরিয়ে ফেলার সেরা উপায়?


147

উদ্দেশ্য-সি NSStringথেকে সদৃশ মান ( ) অপসারণ করার সর্বোত্তম উপায় NSMutableArray?

এটি কি এটি করার সবচেয়ে সহজ এবং সঠিক উপায়?

uniquearray = [[NSSet setWithArray:yourarray] allObjects];

5
আপনি ঠিক একই জিনিসটির রেফারেন্সগুলি মুছে ফেলতে চান কিনা তা স্পষ্ট করে বলতে চাইলে, বা স্বতন্ত্র বস্তুগুলির ক্ষেত্রেও তবে প্রতিটি ক্ষেত্রে একই মান রয়েছে কিনা তা আপনি স্পষ্ট করতে চাইতে পারেন।
Amagrammer

অ্যারের কোনও অনুলিপি তৈরি না করে এটি করার কোনও উপায় নেই?
hfossli

এই উপায়টি যথেষ্ট সহজ এবং সম্ভবত সেরা। তবে উদাহরণস্বরূপ এটি আমার ক্ষেত্রে কার্যকর হবে না - অ্যারের আইটেমগুলি সম্পূর্ণ সদৃশ নয় এবং একটি সংস্থার সাথে তুলনা করা উচিত।
ভাইচাসলভ গার্চিকভ

এটি একবারের জন্য চেষ্টা করুন .. stackoverflow.com/a/38007095/3908884
দোশি

উত্তর:


242

আপনার NSSetপন্থাটি সর্বোত্তম যদি আপনি বস্তুর ক্রম সম্পর্কে উদ্বিগ্ন না হন তবে আবার যদি আপনি আদেশ সম্পর্কে উদ্বিগ্ন না হন তবে কেন আপনি সেগুলি NSSetশুরু করার জন্য সংরক্ষণ করছেন না ?

আমি নীচে উত্তরটি 2009 সালে লিখেছি; ২০১১-এ, অ্যাপল NSOrderedSetআইওএস 5 এবং ম্যাক ওএস এক্স 10.7-এ যুক্ত করেছে। অ্যালগরিদম যা ছিল তা এখন দুটি লাইনের কোড:

NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
NSArray *arrayWithoutDuplicates = [orderedSet array];

যদি আপনি অর্ডারটি সম্পর্কে উদ্বিগ্ন হন এবং আপনি আইওএস 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];

53
আপনার যদি স্বতন্ত্রতা এবং শৃঙ্খলার প্রয়োজন হয় তবে কেবল ব্যবহার করুন [NSOrderedSet orderedSetWithArray:array];আপনি তারপরে একটি অ্যারে ফিরে পেতে পারেন array = [orderedSet allObjects];বা কেবলমাত্র প্রথম স্থানে না ব্যবহার করে NSOrderedSets NSArray
রেজেক্সিডেন্ট

10
@ রেজেক্সিডেন্টের সমাধানটি আদর্শ। শুধু [orderedSet allObjects]সঙ্গে প্রতিস্থাপন করা প্রয়োজন [orderedSet array]!
ইনিকেট দিন

খুব ভাল;) আমি উত্তরটি পছন্দ করি যা বিকাশকারীকে অনেকগুলি পরিবর্তন ছাড়াই অনুলিপি করে কপি করে দেয়, এটিই প্রতিটি উত্তর বিকাশকারী পছন্দ করবে;) @ abo3atef
Abo3atef

ধন্যবাদ তবে আপনার উদাহরণ ঠিক করা উচিত। কারণ - আমরা সাধারণত থাকি NSArrayএবং তৈরি করি NSMutableArray। আপনার উদাহরণে আপনি বিপরীতে কাজ করেন
ভাইচাস্লাভ জেরচিকভ

ডুপ্লিকেট অপসারণ করার জন্য সর্বোত্তম দৃষ্টিতে যে কেউ জানেন যে এই পদ্ধতিটি (ব্যবহার করে NSSet) বা @ সিমন হুইটেকার লিঙ্কটি হ'ল ডুপ্লিকেট মান যুক্ত করার আগে প্রতিরোধ করতে পারে যা দক্ষ উপায়?
মথি আরসান

78

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে NSArray আপনি যদি অর্ডারটি যত্ন না করেন তবে নকলকে সরিয়ে ফেলার আরও একটি দুর্দান্ত উপায় রয়েছে ।

যদি আমরা কী মান কোডিং থেকে অবজেক্ট অপারেটর ব্যবহার করি তবে আমরা এটি করতে পারি:

uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];

হিসাবে AnthoPak লক্ষনীয় এটি একটি সম্পত্তি উপর ভিত্তি করে সদৃশ অপসারণ করা সম্ভব। একটি উদাহরণ হবে:@distinctUnionOfObjects.name


3
হ্যাঁ, আমিও এটি ব্যবহার করি! এটি একটি খুব শক্তিশালী পদ্ধতির, যা অনেকগুলি আইওএস বিকাশকারী জানেন না!
লেফটারিস

1
আমি যখন জানলাম যে এটি সম্ভব হতে পারে তখন আমি অবাক হয়েছিলাম। আমি ভেবেছিলাম যে অনেকগুলি আইওএস বিকাশকারী এটি জানতে পারবেন না সে কারণেই আমি এই উত্তরটি যুক্ত করার সিদ্ধান্ত নিয়েছিলাম :)
টিয়াগো আলমেডা

12
এটি বস্তুর ক্রম বজায় রাখে না।
রুডল্ফ আদমকোভিč

2
হ্যাঁ, এটি অর্ডার ভঙ্গ করে।
রোস্টিস্লাভ দ্রুজচেঙ্কো

নোট করুন যে এটি @distinctUnionOfObjects.propertyকাস্টম অবজেক্টগুলির একটি অ্যারের সম্পত্তি দ্বারা সদৃশগুলি সরানোর মতোও ব্যবহার করা যেতে পারে । উদাহরণস্বরূপ@distinctUnionOfObjects.name
অ্যান্থোপাক

47

হ্যাঁ, এনএসএসেট ব্যবহার করা একটি বোধগম্য পদ্ধতি।

জিম পালসের উত্তরে যুক্ত করতে, অর্ডার বজায় রেখে ডুপ্লিকেটগুলি সরিয়ে ফেলার বিকল্প বিকল্প এখানে রয়েছে:

// Initialise a new, empty mutable array 
NSMutableArray *unique = [NSMutableArray array];

for (id obj in originalArray) {
    if (![unique containsObject:obj]) {
        [unique addObject:obj];
    }
}

এটি মূলত জিমের মতোই একই পদ্ধতির তবে অনুলিপি আইটেমগুলিকে আসল থেকে নকল মুছে ফেলার পরিবর্তে একটি তাজা পরিবর্তনযোগ্য অ্যারে অনুলিপি করে। প্রচুর নকল (পুরো অ্যারের একটি অনুলিপি তৈরি করার প্রয়োজন নেই) সহ বৃহত অ্যারের ক্ষেত্রে এটি সামান্য আরও মেমরির দক্ষ করে তোলে এবং আমার মতে এটি আরও কিছুটা পাঠযোগ্য read

মনে রাখবেন যে উভয় ক্ষেত্রেই, কোনও আইটেম ইতিমধ্যে লক্ষ্য অ্যারেতে অন্তর্ভুক্ত রয়েছে কিনা তা পরীক্ষা করে নেওয়া ( containsObject:আমার উদাহরণে বা indexOfObject:inRange:জিমের ব্যবহার করে) বড় অ্যারেগুলিতে ভাল স্কেল করে না। এই চেকগুলি ও (এন) সময়ে চালিত হয়, এর অর্থ আপনি যদি মূল অ্যারের আকার দ্বিগুণ করেন তবে প্রতিটি চেক চালাতে দ্বিগুণ সময় নিতে হবে। যেহেতু আপনি অ্যারেতে প্রতিটি বস্তুর জন্য চেক করছেন, তাই আপনি আরও বেশি ব্যয়বহুল চেকগুলি আরও চালাবেন। সামগ্রিক অ্যালগরিদম (আমার এবং জিম উভয়ই) ও (এন 2 ) সময়ে চলে যা মূল অ্যারে বাড়ার সাথে সাথে ব্যয়বহুল হয়ে ওঠে।

ও (এন) এর সময় নেওয়ার জন্য আপনি NSMutableSetইতিমধ্যে নতুন অ্যারেতে যুক্ত হওয়া আইটেমগুলির একটি রেকর্ড সংরক্ষণ করতে একটি ব্যবহার করতে পারেন , যেহেতু এনএসএসেট লকআপগুলি ও (এন) এর পরিবর্তে ও (1) হয়। অন্য কথায়, কোনও উপাদান এনএসএসেটের সদস্য কিনা তা যাচাই করতে সেটে কতগুলি উপাদান রয়েছে তা নির্বিশেষে একই সময় নেয়।

এই পদ্ধতির সাহায্যে কোডটি দেখতে এরকম কিছু দেখতে পাবে:

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 থেকে অ্যারের শেষ অবজেক্টে প্রতিটি উপাদানকে লুপ করে তোলে) , তাদের পূর্বের সূচকে সরানো।

তো এখন কি করা? এটা পরিস্থিতির উপর নির্ভর করে। যদি আপনি একটি বড় অ্যারে পেয়ে থাকেন এবং আপনি কেবলমাত্র কয়েকটি সংখ্যক নকলের প্রত্যাশা করছেন তবে স্থানের ডি-সদৃশটি ঠিক কাজ করবে এবং আপনাকে একটি সদৃশ অ্যারে তৈরির সংরক্ষণ করবে। যদি আপনি এমন একটি অ্যারে পেয়ে থাকেন যেখানে আপনি প্রচুর নকলের প্রত্যাশা করছেন তবে আলাদা, ডি-ডুপড অ্যারে তৈরি করা সম্ভবত সেরা পন্থা। এখানে সরানোর বিষয়টি হ'ল বিগ-ও স্বরলিপিটি কেবল একটি অ্যালগরিদমের বৈশিষ্ট্য বর্ণনা করে, এটি আপনাকে নির্দিষ্ট করে বলতে পারে না যে কোনও প্রদত্ত পরিস্থিতিতে সবচেয়ে ভাল।


20

আপনি যদি আইওএস 5+ (পুরো আইওএস ওয়ার্ল্ড জুড়ে) কে লক্ষ্য করে নিচ্ছেন তবে সেরা ব্যবহার করুন NSOrderedSet। এটি সদৃশগুলি সরায় এবং আপনার ক্রমটি ধরে রাখে NSArray

শুধু কর

NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];

আপনি এখন এটি একটি অনন্য NSArray এ আবার রূপান্তর করতে পারেন

NSArray *uniqueArray = orderedSet.array;

কারণ এটি মতো NSArray মত একই পদ্ধতি আছে অথবা শুধু orderedSet ব্যবহার objectAtIndex:, firstObjectইত্যাদি।

এর সাথে সদস্যপদ পরীক্ষা containsকরা তার NSOrderedSetচেয়ে দ্রুততর হয় anNSArray

আরও চেকআউট করার জন্য এনএসআরআরডসেট রেফারেন্স


এটি আমার ভোট পেয়েছে, আমি সেগুলি পড়েছি এবং এটি সেরা উত্তর। বিশ্বাস করা যায় না শীর্ষ উত্তরটি একটি ম্যানুয়াল লুপ। ওহ তারা এখন এই উত্তরটি অনুলিপি করেছে।
মালহাল

19

ওএস এক্স v10.7 এবং তার পরে পাওয়া যায়।

আপনি যদি অর্ডার সম্পর্কে উদ্বিগ্ন হন তবে সঠিক উপায় way

NSArray *no = [[NSOrderedSet orderedSetWithArray:originalArray]allObjects];

অর্ডার ইন এনএসআরাই থেকে সদৃশ মানগুলি অপসারণের কোডটি এখানে।


1
allObjects অ্যারে হওয়া উচিত
ম্যালাল 14'16

7

আদেশ প্রয়োজন

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

3

এখানে আমি মেনআর্রে থেকে অনুলিপি নামের মানগুলি সরিয়েছি এবং এনএসমেটেবালআরির তালিকার ফলাফল (listOfUserrs)

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

1

মনে রাখবেন যে আপনার যদি সাজানো অ্যারে থাকে তবে আপনাকে অ্যারেতে থাকা সমস্ত আইটেমের বিরুদ্ধে চেক করার দরকার নেই, কেবলমাত্র শেষ আইটেম। এটি সমস্ত আইটেমের বিরুদ্ধে চেক করার চেয়ে অনেক দ্রুত হওয়া উচিত।

// 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পরিবর্তে যদি কেবল NSNumberএস বা জাস্ট NSDateগুলি থাকে তবে আপনি প্রতিস্থাপন করতে পারেন

if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])

সঙ্গে

if ([[sortedSourceArray objectAtIndex:i] compare:[sortedSourceArray objectAtIndex:(i-1)]] != NSOrderedSame)

এবং এটি পুরোপুরি কাজ করা উচিত। যদি s, s এবং / অথবা s এর sortedSourceArrayমিশ্রণ থাকে তবে এটি সম্ভবত ক্রাশ হবে।NSStringNSNumberNSDate



1

আর একটি সহজ উপায় আপনি চেষ্টা করে দেখতে পারেন যা অ্যারেতে অবজেক্ট যুক্ত করার আগে সদৃশ মান যুক্ত করবে না: -

// ধরুন পরিবর্তনীয়আরিকে বরাদ্দ দেওয়া হয়েছে এবং আরম্ভ করা হবে এবং এতে কিছু মান রয়েছে

if (![yourMutableArray containsObject:someValue])
{
   [yourMutableArray addObject:someValue];
}

1

উদ্দেশ্য-সি-তে NSMutableArray থেকে সদৃশ মানগুলি সরান

NSMutableArray *datelistArray = [[NSMutableArray alloc]init];
for (Student * data in fetchStudentDateArray)
{
    if([datelistArray indexOfObject:data.date] == NSNotFound)
    [datelistArray addObject:data.date];
}

0

এনএসমিটেবল অ্যারে থেকে সদৃশ মানগুলি অপসারণের কোডটি এখানে। .এটি আপনার পক্ষে কাজ করবে। মাইআরাই আপনার মিউটেটেবল অ্যারে যা আপনি সদৃশ মানগুলি মুছতে চান ..

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

0

ব্যবহারটি Orderedsetকৌশলটি করবে। এটি অ্যারে থেকে অপসারণের সদৃশগুলি রাখবে এবং অর্ডারটি বজায় রাখবে যা সাধারণত সেট করে না


-3

এই সহজ কোডটি ব্যবহার করুন:

NSArray *hasDuplicates = /* (...) */;
NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects];

যেহেতু nsset সদৃশ মানকে অনুমতি দেয় না এবং সমস্ত বস্তু একটি অ্যারে প্রদান করে returns


আমার জন্য কাজ করেছেন। আপনাকে যা করতে হবে তা হ'ল আপনার এনএসআরিকে আবার বাছাই করা হওয়ায় এনএসএসেট একটি অনিবন্ধিত এনএসএরিকে ফেরত দেয়।
লিন্ডিনেক্স

বা সহজভাবে NSOrderedSetinsteed ব্যবহার করুন NSSet
lindinax
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.