2010-06-19 31 views
48

Cách tìm kiếm một NSSet hoặc NSArray cho một đối tượng có giá trị cụ thể cho một thuộc tính cụ thể?Làm thế nào để tìm kiếm một NSSet hoặc NSArray cho một đối tượng có giá trị cụ thể cho một thuộc tính cụ thể?

Ví dụ: Tôi có một NSSet với 20 đối tượng và mọi đối tượng đều có thuộc tính type. Tôi muốn lấy đối tượng đầu tiên có [theObject.type isEqualToString:@"standard"].

Tôi nhớ rằng có thể sử dụng các vị từ bằng cách nào đó cho loại nội dung này, đúng không?

Trả lời

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

NB: Khái niệm của đối tượng tìm thấy đầu tiên trong một NSSet chẳng có ý nghĩa kể từ thứ tự của các đối tượng trong một bộ là không xác định.

+0

Liệu nó có tác dụng nếu đối tượng không có 'loại' bất động sản, nhưng có một đối tượng khác (giả sử 'công việc'), và đây là 'công việc' có thuộc tính 'loại'? – darksider

+0

Có, nhưng một lớp phải tuân thủ mã hóa khóa-giá trị cho các khóa bạn muốn sử dụng trong một biến vị ngữ. –

+0

'indexOfObjectPassingTest' có vẻ tốt hơn vì hai lý do: (1) Bạn sử dụng phương thức thực tế thay vì * chuỗi * (2) Bạn dừng lại trên phần tử" đầu tiên "bạn tìm thấy - không quan trọng là tập hợp không được đặt hàng, bạn vẫn có thể chỉ muốn một mục. –

4
NSArray* results = [theFullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.type LIKE[cd] %@", @"standard"]]; 
17
Bạn có thể lấy mảng lọc như Jason và Ole đã mô tả, nhưng vì bạn chỉ muốn một đối tượng, tôi muốn sử dụng - indexOfObjectPassingTest: (nếu nó nằm trong một mảng) hoặc -objectPassingTest: (nếu nó nằm trong bộ) và tránh tạo mảng thứ hai.
+1

Điều đó có vẻ là một ý tưởng hay đối với NSArray, nhưng phương thức trong NSSet thực sự là '-objectsPassingTest:' (lưu ý số nhiều), vì vậy ý ​​tưởng này không thể trực tiếp ở đó, nếu tôi hiểu điều này một cách chính xác. – Ashley

13

Nói chung, tôi sử dụng indexOfObjectPassingTest: vì tôi thấy thuận tiện hơn khi thể hiện thử nghiệm của mình trong mã Mục tiêu-C thay vì cú pháp NSPredicate. Dưới đây là một ví dụ đơn giản (tưởng tượng rằng integerValue thực sự là một tài sản):

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); 

Kết quả của mã này là:

hasTwo: YES (index was 2) 
hasFour: NO (index was 2147483647) 
Các vấn đề liên quan