【问题标题】:Filtration by Comparison of Dictionary Objects in NSArrayNSArray中字典对象比较过滤
【发布时间】:2014-03-07 05:52:23
【问题描述】:

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

假设我有一个包含以下三个字典的数组,其中 @"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 是重复的,我想从上面的数组中删除字典 1 或字典 2(不是两者)。换句话说,我想将所有三个字典的原始数组过滤成一个新数组,其中包含字典 1 和 3 或字典 2 和 3。

到目前为止,我所做的所有尝试都导致了过多的 for 循环,在其中我尝试按 threadId 对字典进行排序和分隔......但后来我陷入了比较部分。我看过按谓词过滤,但看起来它只删除满足特定条件的对象,与与其他对象的比较无关。 NSSet 不起作用,因为我认为是重复的对象实际上并不是重复的。

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

【问题讨论】:

标签: ios objective-c nsarray nsdictionary


【解决方案1】:

此代码首先为您的字典排序,然后检查是否重复

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

【讨论】:

  • 谢谢!每次迭代只需将线程和主题重置为零。效果很好。
【解决方案2】:

您可以使用嵌套的 for 循环来执行此操作,其中外循环遍历所有元素(最后一个除外),而内循环遍历从当前位置到末尾的所有元素。如果您发现一对相等,您可以将内部循环中的一对添加到NSMutableSet。完成后,您只需从数组中删除 NSMutableSet 中的所有元素。

【讨论】:

    【解决方案3】:

    到目前为止,我所做的所有尝试都导致过度 循环,我尝试在其中对字典进行排序和分隔 线程ID。

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

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

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

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

    【讨论】:

    • 我认为这只有在它们首先排序时才有效,而这段代码没有这样做。答案并没有说明它已经排序。
    • @Gavin 这就是为什么我将用户的评论粘贴在“排序”上,但我同意,我会编辑答案。谢谢!
    【解决方案4】:

    这应该可行:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2011-05-04
        • 1970-01-01
        • 2012-07-18
        • 1970-01-01
        • 2015-10-02
        • 2013-08-19
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        相关资源
        最近更新 更多