2010-06-19 9 views
48

Wie ein NSSet oder NSArray für ein Objekt mit einem bestimmten Wert für eine bestimmte Eigenschaft suchen?Wie wird ein NSSet oder NSArray nach einem Objekt mit einem bestimmten Wert für eine bestimmte Eigenschaft durchsucht?

Beispiel: Ich habe ein NSSet mit 20 Objekten und jedes Objekt hat eine type Eigenschaft. Ich möchte das erste Objekt bekommen, das [theObject.type isEqualToString:@"standard"] hat.

Ich erinnere mich, dass es möglich war, Prädikate irgendwie für diese Art von Sachen zu verwenden, richtig?

Antwort

76
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == %@", @"standard"]; 
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate]; 
id firstFoundObject = nil; 
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil; 

NB: Der Begriff des ersten gefundene Objekts in einem NSSet macht keinen Sinn, da die Reihenfolge der Objekte in einem Satz nicht definiert ist.

+0

Funktioniert es, wenn das Objekt nicht über die ‚Art‘ Eigenschaft, aber hat ein anderes Objekt (sagen wir "Job"), und das ist "Job" mit der Eigenschaft "type"? – darksider

+0

Ja, aber eine Klasse muss für die Schlüssel, die Sie in einem Vergleichselement verwenden möchten, mit Schlüsselwerten codiert sein. –

+0

'indexOfObjectPassingTest' scheint aus zwei Gründen besser: (1) Sie verwenden eine tatsächliche Methode anstelle einer * Zeichenkette * (2) Sie stoppen auf dem" ersten "Element, das Sie finden - es spielt keine Rolle, dass eine Menge nicht geordnet ist, Vielleicht möchten Sie immer noch nur einen Gegenstand. –

4
NSArray* results = [theFullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.type LIKE[cd] %@", @"standard"]]; 
17

Sie können das gefilterte Array als Jason und Ole beschrieben haben, aber da Sie nur ein Objekt wollen, würde ich verwenden - indexOfObjectPassingTest: (wenn es in einem Array ist) oder -objectPassingTest: (wenn es in einem Satz ist) und vermeiden die Schaffung zweites Array.

+1

Das scheint eine gute Idee für ein NSArray zu sein, aber die Methode in NSSet ist eigentlich '-ObjektePassingTest:' (beachte den Plural), also ist diese Idee dort nicht direkt möglich, wenn ich das richtig verstehe. – Ashley

13

Im Allgemeinen verwende ich indexOfObjectPassingTest:, da ich es bequemer finde, meinen Test in Objective-C-Code statt NSPredicate Syntax auszudrücken. Hier ist ein einfaches Beispiel (sich vorstellen, dass integerValue war eigentlich eine Eigenschaft):

NSArray *array = @[@0,@1,@2,@3]; 
NSUInteger indexOfTwo = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
    return ([(NSNumber *)obj integerValue] == 2); 
}]; 
NSUInteger indexOfFour = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
    return ([(NSNumber *)obj integerValue] == 4); 
}]; 
BOOL hasTwo = (indexOfTwo != NSNotFound); 
BOOL hasFour = (indexOfFour != NSNotFound); 
NSLog(@"hasTwo: %@ (index was %d)", hasTwo ? @"YES" : @"NO", indexOfTwo); 
NSLog(@"hasFour: %@ (index was %d)", hasFour ? @"YES" : @"NO", indexOfFour); 

Der Ausgang dieses Codes ist:

hasTwo: YES (index was 2) 
hasFour: NO (index was 2147483647) 
Verwandte Themen