通过比较NSArray中的字典对象进行过滤

时间:2014-03-06 21:14:49

标签: ios objective-c nsarray nsdictionary

我有一系列字典,我需要以非常具体的方式进行过滤。最简单的例子就是解释。

假设我有一个包含以下三个词典的数组,其中@“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(不是两者)。换句话说,我想将所有三个词典的原始数组过滤成一个包含EITHER词典1和3 OR词典2和3的新数组。

到目前为止,我尝试这样做的所有尝试都导致过多的for循环,我试图通过threadId对字典进行排序和分离......但后来我陷入了比较部分。我已经看过谓词过滤,但看起来它只会删除符合特定条件的对象,这些条件与其他对象的比较无关。 NSSet将无法工作,因为我正在考虑重复的对象实际上并不重复。

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

5 个答案:

答案 0 :(得分:0)

你可以使用嵌套的for循环来实现它,其中外部循环遍历所有元素(除了最后一个元素),并且内部循环遍历从当前位置到结尾的所有元素。如果找到一对相等的,则可以将内循环中的一个添加到NSMutableSet。完成后,您只需从数组中删除NSMutableSet中的所有元素。

答案 1 :(得分:0)

  

到目前为止,我尝试这样做的所有尝试都导致过度   循环,我试图通过排序和分隔字典   的threadId。

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

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

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

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

答案 2 :(得分:0)

这应该有效:

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];
    }
}

答案 3 :(得分:0)

此代码首先对您的词典进行排序,并在检查后是否重复

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];
        }
    }
}

答案 4 :(得分:0)

使用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];
    }
}