3

I have an NSObject with NSStrings inside. How do I add objects with unique obj.name only to an NSMutableArray? I tried NSOrderedSet but it only works if you add NSString to an array and not objects with NSString inside.

Example.

@@interface MyObject : NSObject
@property (strong, nonatomic) NSString *name;
@end


NSMutableArray *array = {MyObject.name,MyObject.name,MyObject.name};

How do I make sure that no two MyObjects have the same name?

Sonny G
  • 1,331
  • 1
  • 12
  • 22

3 Answers3

5

Use NSPredicate for seraching object in NSMutableArray if not present then add it to NSMutableArray. Try this.

  NSArray * filtered = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name = %@", @"MyObject.name"]];
  if(![array count])
        [array addObject:MyObject ]; 
Rocker
  • 1,269
  • 7
  • 15
1

All NSSet classes use isEqual: in combination with hash: to compare equality. Because you have not redefined these simply storing two objects with the same name in a set will be possible as the NSObject implementation of isEqual: and hash: will be used.

The documentation of NSObject Protocol talks about overriding isEqual and hash. This previous answer on Stackoverflow details how to implement hash and isEqual correctly.

In your own implementation of hash you can use NSString's hash method.

Example

- (NSUInteger) hash {
    NSUInteger prime = 31;
    NSUInteger result = 1;

   result = prime * result + [super hash];
   result = prime * result + self.name == nil ? 0 : [self.name hash];

   return result;
}

- (bool) isEqual:(id)other {
   if (other == self) {
       return YES;
   }
   if (!other || ![other isKindOfClass:[self class]]) {
        return NO;
   }

   return [self.name isEqualToString:other.name];
}
Community
  • 1
  • 1
Hugo Tunius
  • 2,869
  • 24
  • 32
0

Personally, I would use a NSMutableDictionary with MyObject.name as the key. That way all you would have to do is this:

if( myDictionary[MyObject.name] == nil )
{
    myDictionary[MyObject.name] = MyObject;
}

Much more efficient than using a regular NSMutableArray based on the number of additions you are doing. Plus if you want to get access to an array of all the values, all you have to do is:

NSArray *array = [myDictionary allValues];

The Big-O Runtime for NSPredicate is O(n) where the dictionary method is O(1).

JonahGabriel
  • 3,066
  • 2
  • 18
  • 28
  • 1
    The question was about array so the answer is offtop. What if we need to access to object storage by some identifier and in the same time we need to have object order? – Vyachaslav Gerchicov Apr 05 '18 at 12:50
  • 1
    @VyachaslavGerchicov If you need ordering, you could use an Array and a Dictionary. Use the dictionary to store the key and index of the object in the array and the array to store the list of ordered objects. Probably not worth it for small arrays, but if you are dealing with a large list of items, the constant lookup speed might be worth it. – JonahGabriel Aug 03 '18 at 22:38