【问题标题】:How to remove all objects with the same property value but one in NSMutableArray如何删除具有相同属性值但在 NSMutableArray 中有一个的所有对象
【发布时间】:2013-09-15 20:24:32
【问题描述】:

我有一个带有 url 字符串属性和标题的历史对象。我想使用包含搜索字符串的 url 搜索所有对象的历史记录,然后删除所有重复项。

示例: 我有一组历史对象,其中 20 个都是“https://www.google.com”,4 个是“https://www.google.com/#q=search”,我想返回一个数组,其中只有一个 url 值为“https://www.google.com”的对象和一个“https://www.google.com/#q=search”的url值

这是我当前的代码,它搜索历史并返回与字符串匹配的所有对象:

    - (NSArray *)historyObjectsContainingQuery:(NSString *)query {
    NSMutableArray *matchingObjects = [[NSMutableArray alloc] init];
    HistoryManager *HM = [HistoryManager sharedInstance];
    for (int i=0; i<[[HM history] count]; i++) {
        //History "days"
        HistoryObject *historyItem = HistoryObject([[HistoryManager sharedInstance] history][i]);

        for (int o=0; o<[historyItem.objects count]; o++) {
            //Each object inn each history day
            HistoryObject *HO = HistoryObject(historyItem.objects[o]);
            if ([HO.title rangeOfString:query options:NSCaseInsensitiveSearch].location != NSNotFound) {
                //history objects with their title containing the query string
                [matchingObjects addObject:HO];
            }
        }
    }
    return matchingObjects;
}

然后我记录每个 url 值:

self.foundInBookmarksAndHistory = [self historyObjectsContainingQuery:textField.text]; for (HistoryObject *HO in self.foundInBookmarksAndHistory) { NSLog(@"%@",HO.url); }

结果如下:

https://www.google.com/
2013-09-15 13:48:49.382 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.384 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.385 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.387 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.388 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.390 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.391 Flow HD[3599:60b] https://www.google.com/search?q=yahoo
2013-09-15 13:48:49.392 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.394 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.395 Flow HD[3599:60b] https://www.google.com/search?q=Sup
2013-09-15 13:48:49.397 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.398 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.400 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.402 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.404 Flow HD[3599:60b] https://www.google.com/
2013-09-15 13:48:49.405 Flow HD[3599:60b] https://www.google.com/

还有很多,我如何删除具有相同值的每个对象?对象不相等,但确实具有相等的 url。

我尝试过 NSPredicate 并使用更多的 for 循环来遍历并找到匹配的对象,但我总是留下 2 个或更多具有相同属性的相同对象。

【问题讨论】:

    标签: ios objective-c nsmutablearray nspredicate nsobject


    【解决方案1】:

    你可以这样做:

    NSMutableSet *seenObjects = [NSMutableSet set];
    NSPredicate *dupPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
        HistoryObject *hObj = (HistoryObject*)obj;
        BOOL seen = [seenObjects containsObject:hObj.title];
        if (!seen) {
            [seenObjects addObject:hObj.title];
        }
        return !seen;
    }];
    NSArray *yourHistoryArray = ... // This is your array which needs to be filtered
    NSArray *yourHistoryArray = [yourHistoryArray filteredArrayUsingPredicate:dupObjectsPred];
    

    【讨论】:

    • dupPred = dupObjectsPred
    【解决方案2】:

    我不确定这是搜索所有对象的最佳方式,但除了我能为您的代码想到的最简单的解决方法是替换

    if ([HO.title rangeOfString:query options:NSCaseInsensitiveSearch].location != NSNotFound) {
                    [matchingObjects addObject:HO];
                }
    

    用这个:

    if ([HO.title rangeOfString:query options:NSCaseInsensitiveSearch].location != NSNotFound) {
                    HistoryObject *temp = HistoryObject(historyItem.objects[o]);
                    [historyItem.objects removeObjectAtIndex:o];
                }
    
    //And after all the `for` loops 
    
    [historyItem.objects addObject:temp];
    

    您删除了所有匹配的对象并将其添加到数组中。

    编辑: 阅读您的编辑后,使用isEqualToString 而不是rangeOfString。 rangeOfString 会在 abcd、abce 和 abcf 中找到单词 abc,这不是你想要的。 isEqualToString for abc 仅对 abc 有效,其他无效。

    【讨论】:

    • 啊,具有 objects 属性的 History 对象是历史天数,我只是想通过每天匹配一个字符串来获取每个历史记录对象之一。所以在我上面的代码中,它每天都经过,然后获取每个对象的 url 属性值与查询匹配。但我得到多个对象(不同),但 url 值是相同的
    • 那么为什么不使用 isEqualToString 而不是 rangeOfString 呢? rangeOfString 将在 abcd、abce 和 abcf 中找到单词 abc。 isEqualToString for abc 仅对 abc 有效,其他无效。
    • 这是一个网络浏览器应用程序。所以这是搜索历史。如果我有一个 url 为“google.com”和类似“search.yahoo.com/…”的历史对象,它不匹配,但它有谷歌,所以我也想要。但我得到的比我需要的多。我用每个值的日志更新了我的帖子。
    • 我的第一个答案仍然有效,使用 isEqualToString ,如果它是 TRUE 删除对象。对所有历史都这样做。完成后将相同的对象读取到您的数组中。
    【解决方案3】:

    如果对象仍然存在,则循环可变数组(必要时将数组更改为可变数组)

    while ([farray containsObject:_data]){
           [farray removeObject:_data];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-27
      • 2020-01-05
      • 1970-01-01
      • 2018-11-18
      相关资源
      最近更新 更多