Vikas Bansal
Vikas Bansal

Reputation: 11788

How to find if an object of a class with same data already exists in a NSMutableArray?

I apologize for this basic question, but I am 2-month new to obj-c.

Problem: I am not able to find if an object with same data already exists in the NSMutableArray.

What I am doing?

ScanDigInfoForTable* sfile = [[ScanDigInfoForTable alloc]init];        
sfile.data = "myData";


int inde = [_DataList indexOfObject:sfile] ;        
if(inde == -1)
    [_DataList addObject:sfile];

ScanDigInfoForTable* sfile2 = [[ScanDigInfoForTable alloc]init];        
sfile2.data = "myData";


inde = [_DataList indexOfObject:sfile2] ;        
if(inde == -1)
    [_DataList addObject:sfile2];

Issue: The _DataList get 2 objects instead of 1. Many thanks in advance for your attention.

S.P: I already know that I may traverse the whole array in a loop in order to check the data already exists. Looking for a better solution as the array may have thousands of records.

Upvotes: 1

Views: 53

Answers (4)

Abhinav
Abhinav

Reputation: 38162

Well, comparing two custom objects is really not that simple for the simple fact there is no defined way to declare equality. It is individual choice to define the rules for equality for the objects they are creating.

In your case, it would be two step process:

Step 1: Implement isEqual: in your ScanDigInfoForTable class. Assuming ScanDigInfoForTable is a model class and that it has three string properties - code, data & itemID (you can have any type).

- (BOOL)isEqual:(ScanDigInfoForTable *)other {
    return [self.code isEqualToString:other.code] && [self.data isEqualToString:other.data] && [self.itemID isEqualToString:other.itemID];
}

Step 2: Call containsObject: method on NSMutableArray. This method would internally call isEqual: to give you the results based on the rules you defined.

// If the object does not exist in the list, we add it

if (![_DataList containsObject:sfile2]) {
    [_DataList addObject:sfile2];
}

Upvotes: 2

quellish
quellish

Reputation: 21254

In Objective-C object equality is determined by the methods -isEqual: and -hash.

When testing object membership in a collection the items of the collection are sent isEqual:. The default implementation only compares the addresses of objects, which is why you are seeing duplicates. Your objects do no provide their own implementation of equality based on the data they contain.

To fix this you can override isEqual: to compare objects based on the data they represent. Using your example in your question, this could just be:

- (BOOL) isEqual:(id)object {
    BOOL result = N0;
    if (object != self){
        if ([object isKindOfClass:[self class]]){
            result = [[self data] isEqual:[(ScanDigInfoForTable *)object data]];
        }
    } else {
      result = YES;
    }
    return result;
}

Mike Ash has a great article about implementing equality. In general, if you are implementing a custom class you should make equality a part of that.

Upvotes: 2

Prabhjot Singh
Prabhjot Singh

Reputation: 102

Something like this?

 NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
 NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
 [set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets

 NSArray* result = [set1 allObjects];

This has the benefit of not looking up the objects in the array, while looping through another array, which has N^2 complexity.

and also set2 doesn't have to be mutable, might as well use just

 NSSet* set2 = [NSSet setWithArray:array2];

Upvotes: -1

Flexicoder
Flexicoder

Reputation: 8511

You can user filteredArrayUsingPredicate for example

NSArray * matches = [_DataList filteredArrayUsingPredicate:
                    [NSPredicate predicateWithFormat:@"data == %@ ",sfile2.data]];
if(matches.count == 0) {
    [_DataList addObject:sfile2];
}

Upvotes: -1

Related Questions