过滤NSArray中字典对象的比较

我有一个字典数组,我需要以非常特定的方式进行过滤。 这是最容易解释的例子。

假设我有一个包含以下三个字典的数组,其中@“threadId”,@“subject”,@“messageId”是键:

NSDictionary #1: @"threadId" : @"1234" @"subject" : @"hello" @"messageId" : @"0001" NSDictionary #2: @"threadId" : @"1234" @"subject" : @"hello" @"messageId" : @"0002" NSDictionary #3: @"threadId" : @"9101" @"subject" : @"goodbye" @"messageId" : @"0005" 

我正在考虑任何具有相同值的字典,它们都是@“threadId”和@“subject”是重复的,即使@“messageId”是不同的。 因此,我认为字典1和字典2是重复的,我想从上面的数组中删除EITHER字典1或字典2(不是两个)。 换句话说,我想过滤所有三个字典的原始数组到一个新的数组,包含他们的字典1和3或字典2和3。

到目前为止,我所做的所有尝试都导致了过多的for循环,其中我尝试通过threadId对字典进行sorting和分隔,但之后我陷入了比较部分。 我已经看过谓词过滤,但它看起来像它只能删除符合特定条件的对象,与其他对象无关。 NSSet将无法工作,因为我认为是重复的对象实际上并不重复。

我想知道是否有人可以提出一个执行此过滤的一般策略。

此代码首先命令你的字典,并检查后,如果它重复或不

 NSSortDescriptor *sortDescriptor; //Order by threadId sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"threadId" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; NSArray *arrayOrdered = [yourArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; NSMutableArray *arrayResult = [NSMutableArray array]; NSString* thread = nil; NSString* subj = nil; for (NSDictionary*dic in arrayOrdered) { if ([thread length] == 0 && [subj length] == 0) { thread = [dic objectForKey:@"threadId"]; subj = [dic objectForKey:@"subject"]; }else{ if ([thread isEqualToString:[dic objectForKey:@"threadId"]]) { if (![subj isEqualToString:[dic objectForKey:@"subject"]]) { //We save it [arrayResult addObject:dic]; }else{ //It´s already kept NSLog(@"repeated dic"); } }else{ [arrayResult addObject:dic]; } } } 

你可以使用一个嵌套for循环,其中外层循环遍历所有的元素(除了最后一个),内层循环遍历从当前位置到结尾的所有元素。 如果你find一个相同的对,你可以将内部循环添加到一个NSMutableSet 。 一旦你完成了,你只需从数组中删除NSMutableSet中的所有元素。

到目前为止,我所做的所有尝试都导致了过多的for循环,其中我尝试按threadId对字典进行sorting和分隔。

我认为这将是战略,所以你走在正确的道路上。

在伪代码(不介意语法)我会这样做;

 String *threadid, *subject; // Important: Array must be already sorted (eg with a sortDescriptor) for (NSDictionary *dict in Array) { if (threadid == dict.threadid && subject == dict.subject) { // mark for removal } threadid = dict.threadid; subject = dict.subject; } 

删除标记意味着将要删除的项目添加到新的数组中,因为在枚举期间,您将无法从数组中删除对象。

这应该工作:

 NSArray *array = ...; // Your array of dictionaries // This is going to be the filtered array: NSMutableArray *unique = [NSMutableArray array]; // Set to keep track of all threadId/subject combinations added so far: NSMutableSet *set = [NSMutableSet set]; for (NSDictionary *d in array) { // Create "sub-dictionary" that contains only the key/value pairs // for determining uniqueness: NSDictionary *tmp = [d dictionaryWithValuesForKeys:@[@"threadId", @"subject"]]; // If we have don't have that combination already ... if (![set containsObject:tmp]) { // ... add the full dictionary to the new array ... [unique addObject:d]; // ... and the threadId/subject combination to the set. [set addObject:tmp]; } } 

简单循环与MutableSet检查复合键的唯一性。

 NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity:messages.count]; NSMutableSet *keysSet = [[NSMutableSet alloc] init]; for (NSDictionary *msg in messages) { NSString *key = [NSString stringWithFormat:@"%@%@", msg[@"threadId"], msg[@"subject"]]; if (![keysSet containsObject:key]) { [filteredArray addObject:msg]; [keysSet addObject:key]; } }