2016-01-25 5 views
0

У меня есть массив «белых списков», и я хочу отфильтровать NSDictionary на основе этих ключей;Фильтр NSDictionary на основе массива ключей

NSArray *whiteList = @["one", "two"]; 
NSDictionary *dictionary = @{ 
    @"one" : @"yes", 
    @"two" : @"yes", 
    @"three" : @"no" 
}; 
NSDictionary *whiteDictionary = [dictionary dictionaryWithValuesForKeys:whiteList]; 

Который производит:

{ 
    one = "yes"; 
    two = "yes; 
} 

Однако если мой словарь не включает в себя один или несколько ключей:

NSArray *whiteList = @["one", "two"]; 
NSDictionary *dictionary = @{ 
    @"one" : @"yes" 
}; 
NSDictionary *whiteDictionary = [dictionary dictionaryWithValuesForKeys:whiteList]; 

я вернусь:

{ 
    one = "yes"; 
    two = "<null>"; 
} 

ли существует способ фильтрации словаря на основе набор ключей без получения ключей, которых не существует.

ответ

1

Если вы не связаны с рекурсивно делать это для коллекций внутри словаря, что-то, как это должно работать:

- (NSDictionary *)dictionaryWithNonNullValuesForKeys:(NSArray *)keys { 
    NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionary]; 
    for (id key in keys) { 
     id value = self[key]; 
     if ([value isKindOfClass:[NSNull class]]) { 
      NSLog(@"Warning, value for key was null, skipping key %@", key); 
     } 
     else { 
      mutableDictionary[key] = value; 
     } 
    } 
    return [mutableDictionary copy]; 
} 
+0

Возможно ли использовать предикат или более функциональную парадигму? – lostintranslation

+0

Вы можете отфильтровать ваши белые клавиши со значением [dictionaryInstance allKeys], однако это не отфильтровывает нули, которые фактически вставляются в коллекцию в качестве заполнителей. – NSIRLConnection

2

Update

Вы могли бы иметь функциональное решение путем фильтрации ключей исходного словаря, а затем построение слова белого списка из списка фильтрованных ключей:

NSDictionary *whiteDictionary = [dictionary dictionaryWithValuesForKeys:[dictionary.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self IN %@", whiteList]]];, 

или в двух строках, объявляя отдельную переменную для предиката, чтобы уменьшить размер линии:

NSPredicate *whitelistPredicate = [NSPredicate predicateWithFormat:@"self IN %@", whiteList]; 
NSDictionary *whiteDictionary = [dictionary dictionaryWithValuesForKeys:[dictionary.allKeys filteredArrayUsingPredicate:whitelistPredicate]];, 

Оригинальный ответ

Полу-функциональный подход будет выглядеть следующим образом :

NSDictionary *whiteDictionary = [dictionary dictionaryWithValuesForKeys:whiteList]; 
whiteDictionary = [whiteDictionary dictionaryWithValuesForKeys:[whiteDictionary keysOfEntriesPassingTest:^(NSString *key, id obj, BOOL *stop) { return obj != [NSNull null]; }]]; 

В качестве альтернативы, вы можете перечислить словарь и скопировать отфильтрованный словарь:

NSMutableDictionary *whiteDictionary = [NSMutableDictionary dictionary]; 
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { 
    if ([whiteList containsObject:key]) { 
     whiteDictionary[key] = obj; 
    } 
} 
Смежные вопросы