Search for an array of strings in an array of dictionaries

I have an array of combinations to look for in another array of dictionaries

An array of dictionaries is as follows:

self.listOfAllContacts

({
    name = "William";
    recordId = 541;
},
{
    name = "Soan";
    recordId = 541;
},
{
    name = "kamal";
    recordId = 541;
},
{
    name = "Elisia";
    recordId = 541;
},  
{
    name = "Ben";
    recordId = 541;
},
{
    name = "Loki";
    recordId = 541;
},
{
    name = "Fraser";
    recordId = 541;
});

An array of combinations looks like this: an array named

self.arrayOfSearchCombinationsFormed

  <__NSArrayM 0x1702518b0>(
    ABCD,
    JK,
    AND,
    MIKE,
    ELI,
    STEV,
    FRASE,
    WIILIA
    )

Existing code in work:

self.filteredContacts = [[NSMutableArray alloc] init];
    NSArray *arrayToTraversed = [[NSArray alloc] initWithArray:self.arrayOfSearchCombinationsFormed];
    for(NSString *combination in arrayToTraversed){
        NSPredicate *predicateInsideLoop = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", combination];
        NSArray *filteredContactByName = [self.listOfAllContacts filteredArrayUsingPredicate:predicateInsideLoop];
        if([filteredContactByName count]>0){
            [self.filteredContacts addObjectsFromArray:filteredContactByName];
        }
        else{
            [self.arrayOfSearchCombinationsFormed removeObject:combination];
        }
    }

This solution is currently inefficient and consumes a lot of memory. Any help would be appreciated.

Also note that any combination not found in the dictionary should be removed from the combination array.

So my question is that I want the most efficient way to search for names in terms of memory allocation. So it uses minimal memory.

+4
5

(NSPredicate*)predicateWithBlock: .

, , .

NSArray *keysArray = @[@"1",@"2",@"3"];    
NSArray *sourceArray = @[@"12",@"2",@"3",@"1",@"2"];

@"12" sourceArray, keysArray, @"12" @"1", . @"1" , @"12" @"1", .

:

- (void)searchWithBlock:(NSArray*)keysArray
{
    NSDate *beginDate = [NSDate date];

    NSMutableSet *keySet = [NSMutableSet set];
    NSPredicate *intersectPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
        for (NSString *str in keysArray) {
            NSString *name = evaluatedObject[@"name"];
            NSRange r = [name rangeOfString:str options:NSCaseInsensitiveSearch];
            if (r.location != NSNotFound) {
                [keySet addObject:str];
                return true;
            }
        }
        return false;
    }];

    NSArray *intersect = [self.listOfAllContacts filteredArrayUsingPredicate:intersectPredicate];
    self.filteredContacts = [[NSMutableArray alloc] initWithArray:intersect];

    self.arrayOfSearchCombinationsFormed = [NSMutableArray arrayWithArray:[keySet allObjects]];

    NSDate *endDate = [NSDate date];
    NSTimeInterval interval = [endDate timeIntervalSinceDate:beginDate];
    NSLog(@"interval is %f",interval);

    NSLog(@"intersect %@\n, filtered key array is %@\n", intersect,keySet);
}

1/3 , . , .

+2

:

NSString *sourceRegexp =
    [NSString stringWithFormat:@".*%@.*", 
        [combinations componentsJoinedByString:@".*|.*"]];

NSPredicate *sourcePredicate =
    [NSPredicate predicateWithFormat:@"name MATCHES[c] %@", sourceRegexp];

NSArray *filteredSource =
    [source filteredArrayUsingPredicate:sourcePredicate];

NSPredicate *combinationsPredicate =
    [NSPredicate predicateWithFormat:
        @"SUBQUERY(%@, $s, $s.name CONTAINS[c] SELF).@count > 0",
        filteredSource];

NSArray *filteredCombinations =
    [combinations filteredArrayUsingPredicate:combinationsPredicate];
+1

, , NSPredicate ?

NSSet *contactsToSearchFor = [NSSet setWithArray:self.arrayOfSearchCombinationsFormed];
NSPredicate *prediate = [NSPredicate predicateWithFormat:@"name IN[cd] %@", contactsToSearchFor];
NSArray *results = [self.listOfAllContacts filteredArrayUsingPredicate:predicate];

XCode, .

+1

binary search algorithm .

, binary search.

: http://oleb.net/blog/2013/07/nsarray-binary-search/

0

: . Swift:

func filterContacts(contacts: [Dictionary<String, String>], searchCombinations: [String]) -> [Dictionary<String, String>]{
   return contacts.filter { dict in
      let name = dict["name"]!
      for string in searchCombinations{
         if name.rangeOfString(string) != nil { return true }
      }
      return false
   }
}

Another more complex solution involves using a suffix tree to store your contact data, if search duration is important.

-1
source

All Articles