2012-11-21 11 views
17

मान लीजिए कि मेरे पास क्लास इवेंट है, और इसमें 2 गुण हैं: एक्शन (एनएसएसटींग) और डेट (एनएसडीएटी)।अपनी ऑब्जेक्ट्स के गुणों की तुलना में सरणी से डुप्लिकेट निकालें

और मान लीजिए कि मेरे पास ईवेंट ऑब्जेक्ट्स की एक सरणी है। समस्या यह है कि "तिथि" गुण मिलान कर सकते हैं।

मुझे डुप्लिकेट को हटाने की आवश्यकता है, जिसका अर्थ है कि उसी तारीख के साथ 2 अलग-अलग ऑब्जेक्ट्स डुप्लिकेट हैं।

मैं स्ट्रिंग्स या एनएसडेट्स की किसी भी सरणी में डुप्लिकेट को हटा सकता हूं, उन्हें तुलना करना आसान है। लेकिन जटिल वस्तुओं के साथ इसे कैसे करें, जहां उनकी संपत्तियों की तुलना की जानी चाहिए?

मुझसे मत पूछो कि मैंने अब तक क्या किया है, क्योंकि मेरे दिमाग में आने वाली एकमात्र चीज एक बबल प्रकार है, लेकिन यह एक नौसिखिया समाधान है, और धीमा है।

काफी किसी भी मदद की अत्यधिक सराहना की जाती है (लिंक, टट्स, कोड)।

अग्रिम धन्यवाद।

संपादित

dasblinkenlight के लिए धन्यवाद, मैं एक कस्टम विधि बना दिया है:

- (NSArray *)removeDuplicatesInArray:(NSArray*)arrayToFilter{ 

    NSMutableSet *seenDates = [NSMutableSet set]; 
    NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) { 
     YourClass *e = (YourClass*)obj; 
     BOOL seen = [seenDates containsObject:e.propertyName]; 
     if (!seen) { 
      [seenDates addObject:e.when]; 
     } 
     return !seen; 
    }]; 
    return [arrayToFilter filteredArrayUsingPredicate:dupDatesPred]; 
} 

यहाँ YourClass अपने क्लास का नाम वस्तु के अंतर्गत आता है है, और propertyName है उस वस्तु की संपत्ति जिसे आप तुलना करने जा रहे हैं।

मान लीजिए self.arrayWithObjects में आपके क्लास की ऑब्जेक्ट्स हैं।

यह पॉप्युलेट करने के बाद,

self.arrayWithObjects = [self removeDuplicatesInArray:self.arrayWithObjects];

का उपयोग करें और आप कर रहे हैं।

सभी क्रेडिट्स dasblinkenlight के लिए। चीयर्स!

+0

काम करता है यदि आप पहले से ही सरणी में मौजूद घटनाओं से किसी अन्य के बराबर तारीख के साथ ईवेंट ऑब्जेक्ट्स को जोड़ने से रोकने के लिए अपमान करते हैं? – LuisEspinoza

+0

नाह, सरणी पहले से ही एक विशाल JSON से आबादी है। प्रक्रिया बहुत जटिल है, मुझे लगता है कि डुप्लिकेट को बाद में निकालना आसान है। –

+0

तिथि के अनुसार सरणी को सॉर्ट करें (जो कई प्रकार के एरे ... एनएसएआरएआरई के कार्यों का उपयोग करके काफी आसान है), फिर सॉर्ट किए गए सरणी के माध्यम से कदम उठाएं, एक नए एनएसएमयूटेबलएरे में कॉपी करें, किसी भी तत्व को छोड़ दें जो पिछले एक जैसा दिनांक है । –

उत्तर

24

आप NSMutableSet तिथियों का निर्माण कर सकते हैं, अपनी घटना सूची को पुन: सक्रिय कर सकते हैं, और केवल उस ईवेंट को जोड़ सकते हैं जिसके लिए आपको पहले सामना नहीं हुआ है।

NSMutableSet *seenDates = [NSMutableSet set]; 
NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) { 
    Event *e = (Event*)obj; 
    BOOL seen = [seenDates containsObject:e.date]; 
    if (!seen) { 
     [seenDates addObject:e.date]; 
    } 
    return !seen; 
}]; 
NSArray *events = ... // This is your array which needs to be filtered 
NSArray *filtered = [events filteredArrayUsingPredicate:dupDatesPred]; 
+0

यह काम किया। आसान, तेज़। एक बार फिर धन्यवाद। –

3

यह काम केवीसी के साथ काम नहीं करेगा। मुझे लगता है कि निम्नलिखित समाधान आपके मामले में काम कर सकता है;

Event *event1 = [[Event alloc] init]; 
event1.name = @"Event1"; 
event1.date = [NSDate distantFuture]; 
Event *event2 = [[Event alloc] init]; 
event2.name = @"Event2"; 
event2.date = [NSDate distantPast]; 
Event *event3 = [[Event alloc] init]; 
event3.name = @"Event1"; 
event3.date = [NSDate distantPast]; 
NSArray *array = @[event1, event2, event3]; 

NSArray *filteredEvents = [array valueForKeyPath:@"@distinctUnionOfObjects.name"]; 
+1

'@ specificUnionOfObjects.name' केवल" नाम "नामक यूनिक्स संपत्ति की एक सरणी लौटाएगा। बाकी वस्तुओं नहीं। – lagos

0

मुझे लगता है कि सबसे प्रभावी तरीका NSDictionary उपयोग करने के लिए मूल्य और कुंजी के रूप में संपत्ति के मूल्य के रूप में वस्तु स्टोर करने के लिए है, और शब्दकोश में किसी भी वस्तु को जोड़ने से पहले आप अगर यह मौजूद है या नहीं जो हे है की जाँच (1) ऑपरेशन, यानीपूरी प्रक्रिया को ले जाएगा हे (एन)

यहाँ कोड

- (NSArray *)removeDuplicatesFromArray:(NSArray *)array onProperty:(NSString *)propertyName { 
    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 

    for (int i=0; i<array.count; i++) { 

     NSManagedObject *currentItem = array[i]; 
     NSString *propertyValue = [currentItem valueForKey:propertyName]; 

     if ([dictionary valueForKey:propertyValue] == nil) { 
      [dictionary setValue:currentItem forKey:propertyValue]; 
     } 
    } 

    NSArray *uniqueItems = [dictionary allValues]; 

    return uniqueItems; 
} 

आप निम्नलिखित

self.arrayWithObjects = [self removeDuplicatesFromArray:self.arrayWithObjects onProperty:@"when"]; 
2
NSMutableArray *leftObjects = [duplicateArray mutableCopy]; 
NSMutableArray *nonDuplicates = [NSMutableArray new]; 
while (leftObjects.count > 0) 
{ 
    YourClass *object = [leftObjects objectAtIndex:0]; 

    // find all objects matching your comaprison equality definition for YourClass 
    NSArray *matches = [leftObjects filteredArrayUsingPredicate: 
         [NSPredicate predicateWithBlock:^BOOL(YourClass *evaluatedObject, NSDictionary *bindings) 
         { 
          return (evaluatedObject.name == object.name); 
         }] ]; 
    [leftObjects removeObjectsInArray:matches]; 

    // add first object (arbitrary, may decide which duplicate to pick) 
    [nonDuplicates addObject:matches.firstObject]; 
} 
0

यहाँ के रूप में उपयोग कर सकते हैं NSArray वर्ग पर एक स्विफ्ट विस्तार है जो निर्दिष्ट संपत्ति के लिए डुप्लीकेट हटा देता है:

extension NSArray { 
/** 
- parameter property: the name of the property to check for duplicates 

- returns: an array of objects without objects that share an identical value of the specified property 
*/ 
    func arrayWithoutObjectsOfDuplicateProperty(property : String) -> [AnyObject] { 
    var seenInstances = NSMutableSet() 

    let predicate = NSPredicate { (obj, bind) -> Bool in 
     let seen = seenInstances.containsObject(obj.valueForKey(property)!) 

     if !seen { 
     seenInstances.addObject(obj.valueForKey(property)!) 
     } 
     return !seen 
     }  
     return self.filteredArrayUsingPredicate(predicate) 
    } 
} 
0

यहां काम कर रहे स्विफ्ट कोड को छीन लिया गया है जो तत्वों के क्रम को रखते हुए डुप्लीकेट हटाते हैं

// Custom Struct. Can be also class. 
// Need to be `equitable` in order to use `contains` method below 
struct CustomStruct : Equatable { 
     let name: String 
     let lastName : String 
    } 

// conform to Equatable protocol. feel free to change the logic of "equality" 
func ==(lhs: CustomStruct, rhs: CustomStruct) -> Bool { 
    return (lhs.name == rhs.name && lhs.lastName == rhs.lastName) 
} 

let categories = [CustomStruct(name: "name1", lastName: "lastName1"), 
        CustomStruct(name: "name2", lastName: "lastName1"), 
        CustomStruct(name: "name1", lastName: "lastName1")] 
print(categories.count) // prints 3 

// remove duplicates (and keep initial order of elements) 
let uniq1 : [CustomStruct] = categories.reduce([]) { $0.contains($1) ? $0 : $0 + [$1] } 
print(uniq1.count) // prints 2 - third element has removed 

और बस अगर आप सोच रहे हैं कि यह कैसे काम करता है जादू को कम - यहाँ बिल्कुल वैसा ही है, लेकिन का उपयोग कर अधिक विस्तार वाक्य रचना

let uniq2 : [CustomStruct] = categories.reduce([]) { (result, category) in 
    var newResult = result 
    if (newResult.contains(category)) {} 
    else { 
    newResult.append(category) 
    } 
    return newResult 
} 
uniq2.count // prints 2 - third element has removed 

आप बस इस कोड को एक स्विफ्ट खेल का मैदान में कॉपी-पेस्ट कर सकते हैं को कम और चारों ओर खेलते हैं।

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