45

I am not sure how to go about this. I have an NSMutableArray (addList) which holds all the items to be added to my datasource NSMutableArray.

I now want to check if the object to be added from the addList array already exists in the datasource array. If it does not exist add the item, if exists ignore.

Both the objects have a string variable called iName which i want to compare.

Here is my code snippet

-(void)doneClicked{
    for (Item *item in addList){
        /*
        Here i want to loop through the datasource array 
        */
        for(Item *existingItem in appDelegate.list){
            if([existingItem.iName isEqualToString:item.iName]){
                // Do not add
            }
            else{
                [appDelegate insertItem:item];
            } 
        }
}

But i find the item to be added even if it exists.

What am i doing wrong ?

1
  • It is a logic mistake, see my answer Commented Jun 9, 2011 at 11:04

9 Answers 9

76

There is a very useful method for this in NSArray i.e. containsObject.

NSArray *array;
array = [NSArray arrayWithObjects: @"Nicola", @"Margherita",                                       @"Luciano", @"Silvia", nil];
if ([array containsObject: @"Nicola"]) // YES
{
    // Do something
}
Sign up to request clarification or add additional context in comments.

Comments

40

I found a solution, may not be the most efficient of all, but atleast works

NSMutableArray *add=[[NSMutableArray alloc]init];

for (Item *item in addList){
        if ([appDelegate.list containsObject:item])
            {}
        else
            [add addObject:item];
}

Then I iterate over the add array and insert items.

Comments

22

Use NSPredicate.

NSArray *list = [[appDelegate.list copy] autorelease];

for (Item *item in addList) {

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"iName MATCHES %@", item.iName];
    NSArray *filteredArray = [list filteredArrayUsingPredicate:predicate];
    if ([filteredArray count] > 0) [appDelegate insertItem:item];
}

11 Comments

+1 nice answer. Also avoids the mutating collection exception that would happen if the method used in the question actually worked.
I tried the above edited solution. First thing, the program crashes without showing any error. Secondly, the Item is added even if it exists in the datasource list
@simon: thanks for the answer. But still the program crashes :( I am just banging my head now :(
@Narayanan, Can you tell in which line the program crashes?
@simon: It crashes where we create the predicate. [NSComparisonPredicate isEqualToString:]: unrecognized selector sent to instance 0x7154070
|
6

Did you try indexOfObject:?

-(void)doneClicked{
    for (Item *item in addList){
        if([appDelegate.list indexOfObject:item] == NSNotFound){
            [appDelegate insertItem:item];
        }
}

UPDATE: You have a logical mistake, not mistake in code. assume the first array is ['a', 'b', 'c'], and the second is ['a', 'x', 'y', 'z']. When you iterate with 'a' through the second array it won't add 'a' to second array in the first iteration (compare 'a' with 'a') but will add during the second (compare 'a' with 'x'). That is why you should implement isEqual: method (see below) in your 'Item' object and use the code above.

- (BOOL)isEqual:(id)anObject {
    if ([anObject isKindOfClass:[Item class]])
        return ([self.iName isEqualToString:((Item *)anObject).iName]);
    else
        return NO;
}

8 Comments

@NR4TR: i want to compare the names alone. Not the entire object
Yes i get it now. But when i use the code you have updated, I get the following error [Item isEqualToString:]: unrecognized selector sent to instance 0x712ee70
Check your isEqual: method implementation inside your Item class
sorry, I do not seem to follow. Item is a class that i created myself and I do not have an isEqual method at all. Can you please help me in detail ?
see updates. just paste this isEqual: method to your Item implementation
|
4

Have a look at NSSet. You can add objects and the object will only be added if the object is unique. You can create a NSSet from an NSArray or vise versa.

Comments

2

You can override isEquals and hash on the object so that it returns a YES / NO based on the comparison of the iName property.

Once you have that you can use...

- (void)removeObjectsInArray:(NSArray *)otherArray

To clean the list before adding all the remaining objects.

3 Comments

First, I want to compare the names alone and not the entire object.
Consider reading documentation about isEquals method, it could help
Yes, the idea of overriding the isEquals is that you can then define what you consider 'equal'. Normally the runtime will look at two objects and if they are not the same instance will return false. By overriding the isEquals method you can say 'actually I don't care if the OBJECTS are not the same, in my eyes, these two items are the same if the name matches.'
2

NR4TR said correctly but i think one break statement is sufficient


if([existingItem.iName isEqualToString:item.iName]){
                // Do not add
break;
            }
 

Comments

1

Convert Lowercase and Trim whitespace and then check..

[string lowercaseString];  

and

NSString *trim = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

Comments

1

You compare the addList's first object and appDelegate.list's first object, if they are not equal, you insert the addList's object. The logic is wrong, you should compare one addList's object with every appDelegate.list's object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.