2013-04-12 2 views
1

Дано NSArray с объектами, каждый из которых имеет NSArray с поплавками, хранящийся как NSNumbers.NSPredicate of multimimensional NSArray

Я пытаюсь создать NSPredicate для фильтрации моего основного массива на основе значений float. Так, например, как получить все объекты, которые имеют значение 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]; 

Но как я могу изменить его для моего 2D NSArray с NSNumbers?

ответ

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)]]; 
Смежные вопросы