Frage

ich habe ein NSArray und ich möchte ein neues erstellen NSArray mit Objekten aus dem ursprünglichen Array, die bestimmte Kriterien erfüllen.Die Kriterien werden durch eine Funktion bestimmt, die a zurückgibt BOOL.

Ich kann eine erstellen NSMutableArray, durchlaufen Sie das Quellarray, kopieren Sie die Objekte, die die Filterfunktion akzeptiert, und erstellen Sie dann eine unveränderliche Version davon.

Gibt es einen besseren Weg?

War es hilfreich?

Lösung

NSArray und NSMutableArray stellen Verfahren Array Inhalt zu filtern. NSArray bietet filteredArrayUsingPredicate: , die ein neues Array zurückgibt Objekte in dem Empfänger enthalten, die das angegebene Prädikat entsprechen. NSMutableArray fügt filterUsingPredicate: , die des Empfängers Inhalt gegen das angegebene Prädikat auswertet und lässt Objekte nur das Spiel. Diese Verfahren werden im folgenden Beispiel veranschaulicht.

NSMutableArray *array =
    [NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];

NSPredicate *bPredicate =
    [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
    [array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.

NSPredicate *sPredicate =
    [NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }

Andere Tipps

Es gibt viele Möglichkeiten, dies zu tun, aber die bei weitem einfachste ist sicherlich die Verwendung [NSPredicate predicateWithBlock:]:

NSArray *filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
    return [object shouldIKeepYou];  // Return YES for each object you want in filteredArray.
}]];

Ich denke, das ist so prägnant wie es nur geht.


Schnell:

Für diejenigen, die mit arbeiten NSArrays in Swift, vielleicht bevorzugen Sie dies sogar mehr Kurzfassung:

nsArray = nsArray.filter { $0.shouldIKeepYou() }

filter ist nur eine Methode Array (NSArray wird implizit mit Swifts überbrückt Array).Es braucht ein Argument:ein Abschluss, der ein Objekt im Array annimmt und a zurückgibt Bool.Zum Schluss kommen Sie einfach zurück true für alle gewünschten Objekte im gefilterten Array.

Wenn Sie OS X 10.6 / iOS 4.0 oder höher sind, sind Sie wahrscheinlich besser dran mit Blöcken als NSPredicate. Siehe -[NSArray indexesOfObjectsPassingTest:] oder schreiben Ihre eigene Kategorie eine handliche -select: oder -filter: Methode ( Beispiel ).

hinzufügen

Möchten Sie jemand anderes um diese Kategorie zu schreiben, testen, usw.? Schauen Sie sich BlocksKit ( array docs ). Und es gibt viele weitere Beispiele von zu finden sind, sagen wir, die Suche nach z.B. "NSArray Block Kategorie wählen „.

Auf der Basis eine Antwort von Clay Bridges, hier ist ein Beispiel für Filterung Blöcke (ändern yourArray zu Ihrem Array Variablennamen und testFunc auf den Namen Ihrer Testfunktion):

yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
    return [self testFunc:obj];
}]];

Unter der Annahme, dass Ihr alle Objekte eines ähnlichen Typs sind Sie eine Methode als eine Kategorie von ihrer Basisklasse hinzufügen könnte, die die Funktion aufruft Sie Ihre Kriterien verwenden. Erstellen Sie dann ein NSPredicate Objekt, das in diesem Verfahren bezieht.

In einiger Kategorie definieren Sie Ihre Methode, die Ihre Funktion verwendet

@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
    return someComparisonFunction(self, whatever);
}
@end

Dann, wo Sie werden Filterung:

- (NSArray *)myFilteredObjects {
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
    return [myArray filteredArrayUsingPredicate:pred];
}

Natürlich, wenn Ihre Funktion gegen Eigenschaften vergleicht nur erreichbar aus Ihrer Klasse kann es nur einfacher, die Funktion der Bedingungen zu einem Prädikat Zeichenfolge zu konvertieren.

NSPredicate ist die Art und Weise Bedingung nextstep zum Aufbau einer Sammlung zu filtern (NSArray, NSSet, NSDictionary).

Zum Beispiel betrachten wir zwei Arrays arr und filteredarr:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

die filteredarr werden sicherlich die Elemente, die das Zeichen c allein enthalten.

, um es einfach diejenigen, die wenig sql Hintergrund zu erinnern ist es

*--select * from tbl where column1 like '%a%'--*

1) select * from tbl -> Sammlung

2) column1 like '% a%' -> NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

3) select * from tbl wo column1 like '% a%' ->

[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

Ich hoffe, das hilft

NSArray + X.h

@interface NSArray (X)
/**
 *  @return new NSArray with objects, that passing test block
 */
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
@end

NSArray + X.m

@implementation NSArray (X)

- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
{
    return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:predicate]];
}

@end

Sie diese Kategorie hier herunterladen können

Zur Kasse dieser Bibliothek

https://github.com/BadChoice/Collection

Es kommt mit vielen einfachen Array-Funktionen, nie wieder eine Schleife schreiben

So können Sie einfach tun:

NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

oder

NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

Der beste und einfachste Weg ist diese Methode Und Pass Array zu erstellen und Wert:

- (NSArray *) filter:(NSArray *)array where:(NSString *)key is:(id)value{
    NSMutableArray *temArr=[[NSMutableArray alloc] init];
    for(NSDictionary *dic in self)
        if([dic[key] isEqual:value])
            [temArr addObject:dic];
    return temArr;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top