如何删除具有相同属性值但在 NSMutableArray 中有一个的所有对象

Posted

技术标签:

【中文标题】如何删除具有相同属性值但在 NSMutableArray 中有一个的所有对象【英文标题】:How to remove all objects with the same property value but one in 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 个或更多具有相同属性的相同对象。

【问题讨论】:

【参考方案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 而不是rangeOfStringrangeOfString 会在 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];

【讨论】:

以上是关于如何删除具有相同属性值但在 NSMutableArray 中有一个的所有对象的主要内容,如果未能解决你的问题,请参考以下文章

当标签没有值但属性存在时,需要 XSLT 删除标签

具有相同值但不同类型的参数的 std::floor 函数的不同值

带有 ggplots 的 for 循环生成具有相同值但标题不同的图形

如何选择在 table1 中有值但在 table2 中为 NULL 的字段表?

字符串文字不允许作为非类型模板参数

如何使用两个键删除数组中的重复项?