5

我有一个NSMutableArray以实体类对象作为其对象的对象。现在我想从中删除不同的对象。考虑以下示例

Entity *entity = [[Entity alloc] init]; 
entity.iUserId = 1;
entity.iUserName = @"Giri"
[arr addObject:entity];

Entity *entity = [[Entity alloc] init]; 
entity.iUserId = 2;
entity.iUserName = @"Sunil"
[arr addObject:entity];

Entity *entity = [[Entity alloc] init]; 
entity.iUserId = 3;
entity.iUserName = @"Giri"
[arr addObject:entity];

Array现在,通过删除重复的 iUserName,我只想要两个对象。我知道迭代的方式,但我想要它而不像predicate或其他方式那样迭代它。如果有人知道,请帮助我。我曾尝试使用[arr valueForKeyPath:@"distinctUnionOfObjects.iUsername"];,但它没有返回完整的对象。

这个问题与之前提出的问题完全不同。先前提出的问题是获取不同的对象是正确的,但它们使用循环&我不想要这个。我希望它来自NSPredicate或任何其他避免循环的简单选项。

4

2 回答 2

4

编辑:如果不手动循环数组并建立一个新数组,您将无法做您想做的事情。下面的答案不起作用,因为它假设最多只有两个重复项。

NSMutableArray *filteredArray = [NSMutableArray array];

for (Entity *entity in arr)
{
    BOOL hasDuplicate = [[filteredArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"iUserName == %@", entity.iUserName]] count] > 0;

    if (!hasDuplicate)
    {
        [filteredArray addObject:entity];
    }
}

这将在构建过滤数组时查找重复项。

开始原始答案

您不能使用 an ,NSSet因为Entity实例必须返回NSOrderedSamein compareTo:,这不是一个好主意,因为您不应该使用名称作为唯一标识符。

您可以使用谓词,但它们仍会在一段O(n^2)时间内循环遍历数组,而无需进行一些优化。

NSArray *filteredArray = [arr filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Entity *evaluatedObject, NSDictionary *bindings) {
    return [[arr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"iUserName == %@", evaluatedObject.iUserName]] count] > 1;
}]];

那会很好的。iUserName您可以通过首先按属性对数组进行排序并对排序后的数组进行线性扫描(在看到第一个重复项时停止)来使其更快。如果您要处理小样本量(例如,不到一万左右),那将是很多工作。这可能不值得你花时间,所以只需使用上面的代码。

于 2013-02-13T14:31:32.160 回答
0

那么你有几个选择(我能想到的)。

  1. 使用 NSSet 而不是 NSArray。
  2. 使用 for 循环(但您不想遍历数组)
  3. 在将名称添加到数组之前,使用谓词搜索 iUserName 查看名称是否存在。

就像是:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"iUserName == 'Giri'"];
NSArray *searchArray = [arr filterUsingPredicate:predicate];
于 2013-02-13T14:19:26.103 回答