2013-04-12 137 views
1

Given是一個帶有對象的NSArray,每個對象都有一個帶有浮點數的NSArray,存儲爲NSNumbers。NSPredicate of multidimensional NSArray

我想創建一個NSPredicate來基於浮點值過濾我的主數組。因此,舉例來說,如何將所有具有值234.6 +/- 0.8的對象作爲子數組中的一個浮點數?

我能爲花車的一維的NSArray做這樣的事情:

float targetFloat = 234.6; 
float delta = 0.8; 

filterPredicate = [NSPredicate predicateWithFormat: @"myFloat > %f AND myFloat < %f", (targetFloat - delta), (targetFloat + delta)]; 
filteredArray = [originalArray filteredArrayUsingPredicate: filterPredicate]; 

但我怎麼用NSNumbers改變它爲我的NSArray 2D?

回答

1

您的謂詞可以訪問通過名稱保存數組的對象的屬性;我在下面的例子中調用了list。然後使用ANY關鍵字檢查數組中的所有值,並使用BETWEEN來確定這些值是否在您選擇的範圍內。

#import <Foundation/Foundation.h> 

@interface Grumolo : NSObject 
@property (copy, nonatomic) NSArray * list; 
@end 

@implementation Grumolo 
- (NSString *)description 
{ 
    return [NSString stringWithFormat:@"%@: %p, list: %@", NSStringFromClass([self class]), self, [self list]]; 
} 
@end 

int main(int argc, const char * argv[]) 
{ 

    @autoreleasepool { 
     float target = 234; 
     float delta = 0.8; 
     NSPredicate * p = [NSPredicate predicateWithFormat:@"ANY list BETWEEN %@", @[@(target-delta), @(target+delta)]]; 

     NSArray * yes = @[@234, @10, @100]; 
     NSArray * yes2 = @[@0, @16, @234]; 
     NSArray * no = @[@1, @2, @3]; 

     Grumolo * g1 = [Grumolo new]; 
     [g1 setList:yes]; 
     Grumolo * g2 = [Grumolo new]; 
     [g2 setList:yes2]; 
     Grumolo * g3 = [Grumolo new]; 
     [g3 setList:no]; 


     NSLog(@"%@", [@[g1, g2, g3] filteredArrayUsingPredicate:p]); 


    } 
    return 0; 
} 

你可能也想嘗試一下predicateWithBlock:,這將讓你表達你想與在每個陣列傳統的循環做什麼,返回YES如果你發現符合您的標準和NO的元素,如果你用盡名單。

NSPredicate * pb = [NSPredicate predicateWithBlock:^BOOL(Grumolo * evaluatedObject, NSDictionary *bindings) { 
     NSArray * list = [evaluatedObject list]; 
     __block BOOL result = NO; 
     [list enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) { 
      BOOL moreThanLower = (NSOrderedDescending == [obj compare:@(target-delta)]); 
      BOOL lessThanUpper = (NSOrderedAscending == [obj compare:@(target+delta)]); 
      if(moreThanLower && lessThanUpper){ 
       *stop = YES; 
       result = YES; 
       return; 
      } 
     }]; 

     return result; 
    }]; 
+0

「任何列表之間」是讓它工作的關鍵。謝謝, – Koen

4

您可以在謂詞中使用「SELF [index]」來訪問子數組的特定元素。 以下謂詞找出所有子陣列,其中第一個元素是在 指定範圍:

float lowValue = 1.5; 
float hiValue = 2.5; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[0] > %f AND SELF[0] < %f", lowValue, hiValue]; 
NSArray *filtered = [array filteredArrayUsingPredicate:predicate]; 

如果你想找到包含子陣列的任何指定範圍內的數量,使用

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY SELF BETWEEN %@", @[@(lowValue), @(hiValue)]];