2

NSPredicateこのメソッドの結果を複製するために使用できると言われました

- (void) clearArrayOut
{
    bool goAgain = false;

    for (int j=0; j<[array count]; j++)
    {
        if ([[array objectAtIndex:j] someMethod] == NO)
        {
            [array removeObjectAtIndex:j];
            goAgain = true;
            break;
        }
    }

    if (goAgain) [self clearArrayOut];
}

NSPredicateカスタムクラスの呼び出しのメソッドの結果に基づいて配列をフィルタリングするを作成するにはどうすればよいですか?

4

3 に答える 3

10

フィルタを適用してコピーを作成するには:

NSArray *filteredArray = [someArray filteredArrayUsingPredicate:
    [NSPredicate predicateWithBlock:^(id object, NSDictionary *bindings) {
        return [object someMethod]; // if someMethod returns YES, the object is kept
    }]];

インプレースをフィルタリングするNSMutableArrayには:

[someMutableArray filterUsingPredicate:
    [NSPredicate predicateWithBlock:^(id object, NSDictionary *bindings) {
        return [object someMethod]; // if someMethod returns YES, the object is kept
    }]];

forただし、小さな配列をフィルタリングする場合は、おそらくループを使用します。ただし、forインデックス変数をデクリメントするか、再帰的に自分自身を呼び出す必要がないように、ループの記述は少し異なります。

- (void)clearArrayOut:(NSMutableArray *)array {
    for (int i = array.count - 1; i >= 0; --i) {
        if (![[array objectAtIndex:i] someMethod]) {
            [array removeObjectAtIndex:i];
        }
    }
}
于 2012-07-11T19:02:24.730 に答える
1

述語に書き込むだけです。たとえば、呼び出されたメソッドを持つオブジェクトがあり、isOdd配列をフィルタリングして、に対してtrueを返すオブジェクトのみを含めると仮定すると、次のisOddように実行できます。

#import <Foundation/Foundation.h>

@interface barfoo : NSObject 
{
    int number;
}

- (BOOL)isOdd;
- (id)initWithNumber:(int)number;

@end

@implementation barfoo

- (NSString *)description
{
    return [NSString stringWithFormat:@"%i", number];
}

- (BOOL)isOdd
{
    return (number % 2);
}
- (id)initWithNumber:(int)tnumber
{
    if((self = [super init]))
    {
        number = tnumber;
    }

    return self;
}

@end


int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSMutableArray *array = [NSMutableArray array];
        for(int i=0; i<10; i++)
        {
            barfoo *foo = [[barfoo alloc] initWithNumber:i];
            [array addObject:[foo autorelease]];
        }

        NSLog(@"%@", array); // prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isOdd == true"]; // This is oure predicate. isOdd must be true for objects to pass
        NSArray *result = [array filteredArrayUsingPredicate:predicate];

        NSLog(@"%@", result);
    }
}

もちろん、これは逆の方法でも機能します。述語を読み取ることもisOdd == false、オブジェクトが渡すための要件をさらに追加することもできます。例isOdd == true AND foo == barNSPredicate構文の詳細については、NSPredicateドキュメントを参照してください。

于 2012-07-11T19:04:06.727 に答える
1

実装は最初は非常に非効率的です。削除を再帰的に続行するのではなく、次のように、オブジェクトが削除された場合に先に進まないようにループを変更できます。

- (void) clearArrayOut {
    int j = 0;
    while (j < [array count]) {
        if ([[array objectAtIndex:j] someMethod] == NO) {
            [array removeObjectAtIndex:j];
        } else {
            j++;
        }
    }
}

filterUsingPredicate:次のように、を使用して同じことを行うことができます。

- (void) clearArrayOut {
    NSPredicate *p = [NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bindings) {
        return [obj someMethod] == NO
    }];
    [array filterUsingPredicate:p];
}
于 2012-07-11T19:04:41.057 に答える