Search code examples
iosobjective-cnsmutablearraynspredicatensobject

How to remove all objects with the same property value but one in NSMutableArray


I have a history object with a url string property and title. I want to search all the history for objects with the url containing a search string, then remove all duplicates.

Example: I have an array of history objects and 20 of them are all "https://www.google.com" and 4 are "https://www.google.com/#q=search", I want to get an array back with only one object with the url value of "https://www.google.com" and one url value of "https://www.google.com/#q=search"

Here is my current code that searches the history and returns all objects matching the string:

    - (NSArray *)historyObjectsContainingQuery:(NSString *)query {
    NSMutableArray *matchingObjects = [[NSMutableArray alloc] init];
    HistoryManager *HM = [HistoryManager sharedInstance];
    for (int i=0; i<[[HM history] count]; i++) {
        //History "days"
        HistoryObject *historyItem = HistoryObject([[HistoryManager sharedInstance] history][i]);

        for (int o=0; o<[historyItem.objects count]; o++) {
            //Each object inn each history day
            HistoryObject *HO = HistoryObject(historyItem.objects[o]);
            if ([HO.title rangeOfString:query options:NSCaseInsensitiveSearch].location != NSNotFound) {
                //history objects with their title containing the query string
                [matchingObjects addObject:HO];
            }
        }
    }
    return matchingObjects;
}

Then i log each url value:

self.foundInBookmarksAndHistory = [self historyObjectsContainingQuery:textField.text]; for (HistoryObject *HO in self.foundInBookmarksAndHistory) { NSLog(@"%@",HO.url); }

and here is the results:

https://www.google.com/
2013-09-15 13:48:49.382 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.384 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.385 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.387 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.388 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.390 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.391 Flow HD[3599:60b] https://www.google.com/search?q=yahoo
2013-09-15 13:48:49.392 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.394 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.395 Flow HD[3599:60b] https://www.google.com/search?q=Sup
2013-09-15 13:48:49.397 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.398 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.400 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.402 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.404 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.405 Flow HD[3599:60b] https://www.google.com/

There is A LOT more, how can i remove each object with that same value? the objects are not equal, but do have equal urls.

I've tried NSPredicate and using more for loops to go through and find matching objects but im always left with 2 or more of the same objects with the same property.


Solution

  • You can do some thing like this :

    NSMutableSet *seenObjects = [NSMutableSet set];
    NSPredicate *dupPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
        HistoryObject *hObj = (HistoryObject*)obj;
        BOOL seen = [seenObjects containsObject:hObj.title];
        if (!seen) {
            [seenObjects addObject:hObj.title];
        }
        return !seen;
    }];
    NSArray *yourHistoryArray = ... // This is your array which needs to be filtered
    NSArray *yourHistoryArray = [yourHistoryArray filteredArrayUsingPredicate:dupObjectsPred];