1

In my app I'me getting responses from the server and I have to check that I don't create duplicate objects in the NSArray which contains NSDictionaries. Now to check if the objects exists I do this:

for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){

   NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];

   if ([[tmpDictionary valueForKey:@"webpropID"] isEqualToString:tmpWebproperty.identifier]){
       needToCheck = NO;
   }

   if (i == appDelegate.currentUser.userSiteDetailsArray.count - 1 && ![[tmpDictionary valueForKey:@"webpropID"] isEqualToString:tmpWebproperty.identifier] && needToCheck){
 // It means it's the last object we've iterated through and needToCheck is still = YES;
        //Doing stuff here
     }
  }

I set up a BOOL value because this iteration goes numerous times inside a method and I can't use return to stop it. I think there is a better way to perform this check and I would like to hear your suggestions about it.

Sergey Grischyov
  • 11,995
  • 20
  • 81
  • 120
  • Have you tried just using an NSSet? Those automatically will not allow duplicates. As long as you properly implement `hash` and `isEqual` for custom objects and aren't using coredata. – Firo Sep 02 '13 at 15:24
  • @Firo and how about the fact that I am creating new instances of `NSDictionary` each time I'm trying to add to `NSSet` or `NSArray` or whatever? – Sergey Grischyov Sep 02 '13 at 15:25
  • It shouldn't matter, when you attempt to add the `NSDictionary` to the set it will send it `isEqual`. If it is a duplicate dictionary based on its values it will not insert it. Unless there is more going on here then I currently am thinking. – Firo Sep 02 '13 at 15:28
  • I'm confused. Once you've set needToCheck to NO you can just `break` out of the loop, since the second `if` condition will never be true. And why do you do the isEqualToString check the second time, when the first check would have set needToCheck to NO and so the second `if` can't be true anyway? And why not just fall out of the loop, check that needToCheck is YES, and *then* do your "doing stuff" logic? – Hot Licks Sep 02 '13 at 15:34
  • @Firo no, nothing matters about the `NSDictionary` but just its values. But the thing here is, unfortunately, I need to enforce strict order of the elements and I don't think an NSSet is an option to me here. – Sergey Grischyov Sep 02 '13 at 15:35

2 Answers2

1
BOOL needToCheck = YES;
for (int i = 0; i < appDelegate.currentUser.userSiteDetailsArray.count; i++){
    NSDictionary *tmpDictionary = [appDelegate.currentUser.userSiteDetailsArray objectAtIndex:i];
    if ([[tmpDictionary valueForKey:@"webpropID"] isEqualToString:tmpWebproperty.identifier]){
        needToCheck = NO;
        break;
    }
 }

 if (needToCheck) {
     //Doing stuff here
 }

But, as others have said, you can maybe keep a "summary" in a separate NSSet that you check first, vs spinning through all the dictionaries.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
1
NSDictionary *previousThing = nil;
for (NSDictionary *thing in appDelegate.currentUser.userSiteDetailsArray) {
    if ([thing[@"webpropID"] isEqualToString:newWebPropertyIdentifier]) {
        previousThing = thing;
        break;
    }
}

if (previousThing == nil) {
    // no previous thing
} else {
    // duplicate
}
Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200