【问题标题】:Get distinct entity objects from NSMutableArray using NSPredicate in iPhone sdk [duplicate]在 iPhone sdk 中使用 NSPredicate 从 NSMutableArray 中获取不同的实体对象 [重复]
【发布时间】:2013-02-13 13:22:21
【问题描述】:

我有一个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 或任何其他避免循环的简单选项。

【问题讨论】:

  • "in iphone sdk" - 谢谢!很久没有人正确使用它了(而不是不恰当的“使用 Xcode”术语)。
  • 我记得我已经解决了3-4次这种问题。所以永远不要对搜索/谷歌感到害羞。
  • @AKV 我想要通过比较实体类对象中的实体来获得不同的元素。我也想避免 for 循环。是否可以通过谓词或任何其他选项

标签: ios objective-c nsmutablearray


【解决方案1】:

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

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 实例必须在compareTo: 中返回NSOrderedSame,这不是一个好主意,因为您不应该使用名称作为唯一标识符。

您可以使用谓词,但它们仍会在 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 属性对数组进行排序并对排序后的数组进行线性扫描(当您看到第一个重复项时停止)来使其更快。如果您要处理小样本量(例如,不到一万左右),那将是很多工作。这可能不值得你花时间,所以只需使用上面的代码。

【讨论】:

  • 我已经尝试过您的解决方案,但它不起作用。我使用了以下代码 NSArray *filteredArray = [arr filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Entity *entity, NSDictionary *bindings) { return [[arr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"iUsername == %@", exercise.iUsername ]] 计数] > 1; }]];
  • 应该可以,是的。
  • 我的数组总共包含 14 个元素,其中 7 个是常见的,所以它需要返回 6 个元素,但它返回 13 个元素。
  • 我收回 - 如果不手动循环,您将无法做到这一点。 NSPredicate 不起作用。查看我的更新答案。
【解决方案2】:

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

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

类似:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 2018-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多