it-swarm.com.de

nSArray in ein neues NSArray in Objective-c filtern

Ich habe eine NSArray und ich möchte eine neue NSArray mit Objekten aus dem ursprünglichen Array erstellen, die bestimmte Kriterien erfüllen. Das Kriterium wird von einer Funktion festgelegt, die eine BOOL zurückgibt.

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

Gibt es einen besseren Weg?

110
lajos

NSArray und NSMutableArray bieten Methoden zum Filtern von Array-Inhalten. NSArray bietet filtersArrayUsingPredicate: , das ein neues Array zurückgibt, das Objekte im Empfänger enthält, die dem angegebenen Prädikat entsprechen. NSMutableArray fügt filterUsingPredicate: hinzu, das den Inhalt des Empfängers anhand des angegebenen Prädikats auswertet und nur übereinstimmende Objekte zurücklässt. Diese Methoden 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" }
132
lajos

Es gibt viele Möglichkeiten, dies zu tun, aber bei weitem wird [NSPredicate predicateWithBlock:] mit Sicherheit verwendet:

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 knapp, wie es nur geht.


Schnell:

Für diejenigen, die in Swift mit NSArrays arbeiten, bevorzugen Sie möglicherweise diese noch mehr prägnante Version:

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

filter ist nur eine Methode für Array (NSArray ist implizit mit Swifts Array verbunden). Es gibt ein Argument: eine Schließung, die ein Objekt im Array übernimmt und eine Bool zurückgibt. In Ihrer Schließung geben Sie einfach true für alle gewünschten Objekte im gefilterten Array zurück.

91
Stuart

Wenn Sie OS X 10.6/iOS 4.0 oder höher verwenden, sind Sie mit Blocks wahrscheinlich besser als mit NSPredicate. Siehe -[NSArray indexesOfObjectsPassingTest:] oder schreibe deine eigene Kategorie, um eine praktische -select:- oder -filter:-Methode ( example ) hinzuzufügen.

Möchten Sie, dass jemand anderes diese Kategorie schreibt, testet usw.? Check out BlocksKit ( array docs ). Und es gibt viele weitere Beispiele, die beispielsweise durch Suchen nach z. "nsarray block category select" .

49
Clay Bridges

Basierend auf einer Antwort von Clay Bridges, hier ein Beispiel für das Filtern mit Blöcken (ändern Sie yourArray in den Namen Ihrer Array-Variablen und testFunc in den Namen Ihrer Testfunktion):

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

Wenn Sie davon ausgehen, dass Ihre Objekte alle einen ähnlichen Typ haben, können Sie eine Methode als Kategorie ihrer Basisklasse hinzufügen, die die für Ihre Kriterien verwendete Funktion aufruft. Erstellen Sie dann ein NSPredicate-Objekt, das auf diese Methode verweist.

Definieren Sie in einigen Kategorien Ihre Methode, die Ihre Funktion verwendet

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

Wo auch immer Sie filtern:

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

Wenn Ihre Funktion nur mit Eigenschaften vergleichbar ist, die innerhalb Ihrer Klasse erreichbar sind, kann es natürlich einfacher sein, die Bedingungen der Funktion in eine Prädikatzeichenfolge umzuwandeln.

16
Ashley Clark

NSPredicate ist die Methode von NeXTSTEP, Bedingungen zu erstellen, um eine Sammlung zu filtern (NSArray, NSSet, NSDictionary).

Betrachten Sie zum Beispiel zwei Arrays arr und filteredarr:

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

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

das gefilterte Haar wird sicherlich die Elemente enthalten, die nur den Buchstaben c enthalten.

um es leicht zu machen, sich an diejenigen zu erinnern, die ein wenig SQL-Hintergrund haben 

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

1) Wählen Sie * aus tbl -> collection aus

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

3) Wähle * aus der Tabelle, wobei Spalte1 wie '% a%' -> steht

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

Ich hoffe das hilft 

3
Durai Amuthan.H

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 können diese Kategorie hier herunterladen

2
skywinder

Überprüfen Sie diese Bibliothek

https://github.com/BadChoice/Collection

Es gibt viele einfache Array-Funktionen, um nie wieder eine Schleife zu schreiben

Sie können also einfach folgendes 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;
}];
0

Der beste und einfachste Weg ist, diese Methode zu erstellen und Array und Wert zu übergeben:

- (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;
}
0
jalmatari