2

I have the following code:

   NSMutableSet* localSet = [[NSMutableSet alloc] initWithArray:symbols];
NSMutableArray* fetchedSymbolsArray = [NSMutableArray array];

for (NSDictionary* symbol in fetchedSymbols) {
    [fetchedSymbolsArray addObject:[NSDictionary dictionaryWithObject:[symbol valueForKey:@"symbol"] forKey:@"symbol"]];
}

NSMutableSet* serverSet = [[NSMutableSet alloc] initWithArray:fetchedSymbolsArray];

[localSet unionSet:serverSet];

for (NSDictionary* symbol in localSet) {
    NSLog(@"%@",[symbol valueForKey:@"symbol"]);
}

I want everything in serverSet to be in localSet. This code does not reflect this.

It would also be preferable if any duplicates were not added to localSet.

EDIT: Here is my log:

2011-08-16 17:46:28.887 Stream[94612:207] YHOO
2011-08-16 17:46:28.887 Stream[94612:207] GOOG
2011-08-16 17:46:28.887 Stream[94612:207] INTC
2011-08-16 17:46:28.888 Stream[94612:207] BIDU
2011-08-16 17:46:28.888 Stream[94612:207] INTC
2011-08-16 17:46:28.888 Stream[94612:207] BIDU
2011-08-16 17:46:28.888 Stream[94612:207] AAPL
2011-08-16 17:46:28.888 Stream[94612:207] AAPL
2011-08-16 17:46:28.889 Stream[94612:207] AMD
2011-08-16 17:46:28.889 Stream[94612:207] GMCR
Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
Sheehan Alam
  • 60,111
  • 124
  • 355
  • 556

2 Answers2

6

try [localSet unionSet:serverSet]

EDIT

Here's code that just uses symbols instead of NSDictionarys:

NSArray *symbols = [NSArray arrayWithObjects:@"AAPL",@"GOOG",@"INTC",@"YHOO",nil];

NSArray *fetchedSymbols = [NSArray arrayWithObjects:@"AMD",@"BIDU",@"GOOG",@"GMCR",@"INTC",@"YHOO",nil];


NSMutableSet* localSet = [[NSMutableSet alloc] initWithArray:symbols];
NSMutableSet* serverSet = [[NSMutableSet alloc] initWithArray:fetchedSymbols];

[localSet unionSet:serverSet];

for (id symbol in localSet) {
    NSLog(@"%@",symbol);
}

2011-08-16 18:25:22.107 so7086790[39810:a0f] YHOO
2011-08-16 18:25:22.116 so7086790[39810:a0f] AMD
2011-08-16 18:25:22.116 so7086790[39810:a0f] AAPL
2011-08-16 18:25:22.116 so7086790[39810:a0f] INTC
2011-08-16 18:25:22.117 so7086790[39810:a0f] GMCR
2011-08-16 18:25:22.117 so7086790[39810:a0f] GOOG
2011-08-16 18:25:22.118 so7086790[39810:a0f] BIDU
SSteve
  • 10,550
  • 5
  • 46
  • 72
  • Cool now they're all added. Problem is there are duplicates. How can I remove dupes from the set? – Sheehan Alam Aug 17 '11 at 00:46
  • That is probably because the members of the set that you are considering equal are not really equal in the way that they are tested by `NSSet` (i.e. they return `false` when sent `isEqual:`). After looking at your log, I'm pretty sure that's the case. The `valueForKey:@"symbol"` result is the same for the dictionaries, but the dictionaries themselves aren't the same. – SSteve Aug 17 '11 at 00:53
  • I see. With this in mind, how can I check for the string value in the dictionary, or remove dupes? – Sheehan Alam Aug 17 '11 at 00:57
  • 2
    If the only thing you care about is the symbol, just add the symbols to the set instead of `NSDictionary`s whose only member is the symbol. If you need to store more than just the symbol create your own class that stores the properties you need and responds to `isEqual:` by comparing its symbol value to the symbol value of the object passed as an argument. – SSteve Aug 17 '11 at 01:02
0

You've got your serverSet and localSet around the wrong way in the union - the set being modified is the receiver of the method "unionSet:", not the argument.

NSMutableSet* localSet = [[NSMutableSet alloc] initWithArray:symbols];
NSMutableArray* fetchedSymbolsArray = [NSMutableArray array];

for (NSDictionary* symbol in fetchedSymbols) {
    [fetchedSymbolsArray addObject:[NSDictionary dictionaryWithObject:[symbol valueForKey:@"symbol"] forKey:@"symbol"]];
}

NSMutableSet* serverSet = [[NSMutableSet alloc] initWithArray:fetchedSymbolsArray];

[localSet unionSet:serverSet];

for (NSDictionary* symbol in localSet) {
    NSLog(@"%@",[symbol valueForKey:@"symbol"]);
}

Note that set's, by definition, won't allow duplicate entries. But that doesn't mean that you won't have duplicates of values within the dictionary, it means that you won't have the same "equal" dictionary twice (two dictionaries are equal if they each hold the same number of entries and, for a given key, the corresponding value objects in each dictionary satisfy the isEqual: test).

To avoid duplicates of a particular dictionary value, you'd have to add them yourself. I'd recommend you create a temporary set which contains the actual values for the "symbol" key and use that set to test whether it's already been added.

NSMutableSet *localSetValues = [[NSMutableSet alloc] init];

// Add local set values
for (NSDictionary *symbol in localSet) {
    [localSetValues addObject:[symbol valueForKey:@"symbol"]];
}
// Add server set, conditionally
for (NSDictionary *symbol in serverSet) {
    if (![localSetValues containsObject:[symbol valueForKey:@"symbol"]]) {
        [localSet addObject:symbol];
    }
}

// Cleanup
[localSetValues release];

Instead of

[localSet unionSet:serverSet];
Johnus
  • 722
  • 6
  • 12
  • I don't think what you're saying about duplicate entries is correct. It seems that NSSet will de-dupe dictionaries which truly are identical. For example, this prints out a set containing only one dictionary, despite two separate instances: NSDictionary *dict1 = [NSDictionary dictionaryWithObject:@"AAPL" forKey:@"symbol"]; NSDictionary *dict2 = [NSDictionary dictionaryWithObject:@"AAPL" forKey:@"symbol"]; NSMutableSet *set = [NSMutableSet setWithObject:dict1]; [set addObject:dict2]; NSLog(@"%@", set); – paulmelnikow Aug 17 '11 at 06:31
  • Yeah you're right, I didn't make the distinction between equal and inequal dictionaries very clear. Updated. – Johnus Aug 18 '11 at 00:48