使用iPhone sdk中的NSPredicate从NSMutableArray中获取不同的实体对象

时间:2013-02-13 13:22:21

标签: ios objective-c nsmutablearray

我有一个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];

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

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

2 个答案:

答案 0 :(得分: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];
    }
}

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

开始原始答案

您无法使用NSSet因为Entity个实例必须在NSOrderedSame中返回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属性对数组进行排序并对已排序的数组执行线性扫描(在看到第一个副本时停止)​​来使速度更快。如果您处理的是小样本(例如,不到一万个左右),这就是很多工作。这可能不值得你花时间,所以只需使用上面的代码即可。

答案 1 :(得分:0)

嗯,你有几个选择(我能想到)。

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

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"iUserName == 'Giri'"];
    NSArray *searchArray = [arr filterUsingPredicate:predicate];