【问题标题】:Filter NSArray based on another array using predicate使用谓词根据另一个数组过滤 NSArray
【发布时间】:2015-01-07 02:04:30
【问题描述】:

考虑下面的数组。数组包含“Alpha”类型的对象。我们只关心username 类型为NSString 的属性。

NSArray *some_usernames = @[ <multiple values of type Alpha> ]
NSArray *all_usernames = @[ <multiple values of type Alpha> ]

我基本上想要一个不在数组some_usernames中的所有用户名的列表,即

NSArray *remaining_usernames = @[ <all_usernames but not in some_usernames> ];

我打算这样做的方式是:

NSPredicates *predicates;
for (Alpha *alpha in some_usernames)
{
    predicate = [predicate with @"username != %@", alpha.username];
    predicates.add(predicate)
}

create compound predicate
filter all_usernames

但这感觉是一种不好的做法。有没有办法在两行中做到这一点?我以前见过,但我不能再指向代码参考了。

【问题讨论】:

    标签: ios objective-c predicate


    【解决方案1】:
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]];
    NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];
    

    完整示例

    @interface Alpha : NSObject
    @property (nonatomic, copy) NSString *username;
    -(instancetype) initWithUsername:(NSString *)username;
    @end
    
    @implementation Alpha
    -(instancetype) initWithUsername:(NSString *)username
    {
        self = [super init];
        if (self) {
            self.username = username;
        }
        return self;
    }
    
    -(NSString *)description{
        return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username];
    }
    @end
    
    
    NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"], [[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"z"], [[Alpha alloc] initWithUsername:@"f"], [[Alpha alloc] initWithUsername:@"e"]];
    NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"f"]];
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username  IN %@)", [some_usernames valueForKey:@"username"]];
    NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];
    
    NSLog(@"%@", remaining_usernames);
    

    打印

    (
        "Alpha: a",
        "Alpha: z",
        "Alpha: e"
    )
    

    【讨论】:

    • 这是 `@"username != %@" 的替代品吗?如果是这样,谢谢。但我不想在这里使用我的方法。
    • 非常感谢它有效。你知道你可以慢慢来。在你的编辑过程中,我一直在敲我的头。 :P 非常感谢。 :)
    【解决方案2】:

    我想补充一个答案:

    如果不需要对象的排序(并且 - 很可能 - 不需要相等的对象),您可以使用集合和集合算术来代替对数组使用谓词过滤。为此,我们必须教Alpha 相等的含义并提供哈希方法。在这种情况下,我们只使用 NSStrings 实现:

    @implementation Alpha
    -(instancetype) initWithUsername:(NSString *)username
    {
        self = [super init];
        if (self) {
            self.username = username;
        }
        return self;
    }
    
    -(NSString *)description{
        return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username];
    }
    
    -(BOOL)isEqual:(id)object
    {
        return [self.username isEqual:[object username]];
    }
    
    -(NSUInteger)hash
    {
        return [self.username hash];
    }
    
    @end
    
    
    
    NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"],
                               [[Alpha alloc] initWithUsername:@"b"],
                               [[Alpha alloc] initWithUsername:@"z"],
                               [[Alpha alloc] initWithUsername:@"f"],
                               [[Alpha alloc] initWithUsername:@"e"]];
    
    NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"],
                                [[Alpha alloc] initWithUsername:@"f"]];
    
    NSSet *allSet = [NSSet setWithArray:all_usernames];
    NSSet *someSet = [NSSet setWithArray:some_usernames];
    
    NSMutableSet *remainingSet = [allSet mutableCopy];
    [remainingSet minusSet:someSet];
    
    NSLog(@"%@", remainingSet);
    

    打印

    {(
        Alpha: z,
        Alpha: e,
        Alpha: a
    )}
    

    对于更多数据,此代码应该更快。请关注WWDC 2013: Designing Code for Performance

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 2019-10-15
      • 1970-01-01
      相关资源
      最近更新 更多