Fast enumeration Arrays of Dictionaries

71 views Asked by At

I have an array of dictionaries in following format.

myarary = {day = 0; hour = 1; value = 0;},{day = 0; hour = 2; value = 0;}.... {day 6 =1; hour =23; value =1;}

So basically 7 days, 24 hours for each day and values 1 or 0 for each hour. hence total of 168 dictionaries in my array.

Now my task is to extract values for a range of hours for a given day. For example, for day 6 I would have to extract hours slot between 2, 9 and another slot between 15 and 18 and so on.

I manage to solve the problem, with a nest for loop in following format

for (i =< start_of_hour_slot;i=<last_hour_of_slot); i++) for(j = 0; j<=6; j++)

Now this works, but its too lengthy and my code is filled with loops, there must be easier way with fast enumeration?

Secondly my for loops doesn't give me flexibility.

I like to be in a position, where I can simply extract lets say for day 7, three different hours slots, along side the values.

or maybe for multiple days like, day 3,4,5 slots 2-9, 11,15...

2

There are 2 answers

1
EricXuan On

You can change your array size and format, since your data is clear, just need to make the array size to 168, and put the value 0 or 1 directly into the array. The first 24 elements put the array the day0 values, and the next 24 elements put the day1 values, ..., the last 24 elements put the day6 values. If you want to extract the values of day 3,4,5 slots 2-9, 11,15, just fetch the elements index of 3*6+2 ~ 3*6+9, 4*6+11, 5*6+15 in the array.

0
R4N On

As @vadian suggested NSCompoundPredicate should work for what you're attempting to accomplish. It looks like you may have a few typos in the NSPredicate you posted in your comments which is why it's failing to parse.

#import "ViewController.h"

@interface ViewController ()
@property (strong, nullable) NSArray <NSDictionary *> *generatedArray;
- (NSArray <NSDictionary *> *)_generateFakeDictionaryArray;
- (NSPredicate *)_predicateForDays:(NSArray <NSNumber *> *)days andHours:(NSArray <NSNumber *> *)hours;
- (NSPredicate *)_predicateForDays:(NSArray <NSNumber *> *)days andHoursBetween:(NSArray <NSNumber *> *)hoursBetween;
- (NSPredicate *)_predicateForDaysBetween:(NSArray <NSNumber *> *)daysBetween andHours:(NSArray <NSNumber *> *)hours;
- (NSPredicate *)_predicateForDaysBetween:(NSArray <NSNumber *> *)daysBetween andHoursBetween:(NSArray <NSNumber *> *)hoursBetween;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.generatedArray = [self _generateFakeDictionaryArray];
}

- (void)viewDidAppear:(BOOL)animated {
    // one day multiple hour slots
    NSPredicate *specificDaysSpecificHours = [self _predicateForDays:@[@(6)] andHours:@[@(7), @(8), @(22)]];
    // multiple days hoursBetween
    NSPredicate *daysBetweenHoursBetween = [self _predicateForDaysBetween:@[@(3), @(5)] andHoursBetween:@[@(2), @(9)]];
    // days between, specific hours
    NSPredicate *daysBetweenSpecificHours = [self _predicateForDaysBetween:@[@(3), @(5)] andHours:@[@(11), @(15)]];
    NSCompoundPredicate *compPred = [NSCompoundPredicate orPredicateWithSubpredicates:@[specificDaysSpecificHours, daysBetweenHoursBetween, daysBetweenSpecificHours]];
    NSArray <NSDictionary *> *filteredArray = [self.generatedArray filteredArrayUsingPredicate:compPred];
    NSLog(@"Filtered array = %@", filteredArray);
}

- (NSArray <NSDictionary *> *)_generateFakeDictionaryArray {
    NSInteger daysInWeek = 7;
    NSInteger hoursInDay = 24;
    NSMutableArray *dictArray = [NSMutableArray arrayWithCapacity:hoursInDay * daysInWeek];
    for (NSInteger day = 0; day < daysInWeek; day++) {
        for (NSInteger hour = 0; hour < hoursInDay; hour++) {
            NSDictionary *dayHourDict = @{@"day" : @(day), @"hour" : @(hour), @"value" : @(arc4random() % 2)};
            [dictArray addObject:dayHourDict];
        }
    }
    return [NSArray arrayWithArray:dictArray];
}

- (NSPredicate *)_predicateForDays:(NSArray <NSNumber *> *)days andHours:(NSArray <NSNumber *> *)hours {
    return [NSPredicate predicateWithFormat:@"day IN %@ AND hour IN %@", days, hours];
}

- (NSPredicate *)_predicateForDays:(NSArray <NSNumber *> *)days andHoursBetween:(NSArray <NSNumber *> *)hoursBetween {
    return [NSPredicate predicateWithFormat:@"day IN %@ AND hour BETWEEN %@", days, hoursBetween];
}

- (NSPredicate *)_predicateForDaysBetween:(NSArray <NSNumber *> *)daysBetween andHours:(NSArray <NSNumber *> *)hours {
    return [NSPredicate predicateWithFormat:@"day BETWEEN %@ AND hour IN %@", daysBetween, hours];
}

- (NSPredicate *)_predicateForDaysBetween:(NSArray <NSNumber *> *)daysBetween andHoursBetween:(NSArray <NSNumber *> *)hoursBetween {
    return [NSPredicate predicateWithFormat:@"day BETWEEN %@ AND hour BETWEEN %@", daysBetween, hoursBetween];
}


@end

Which generates this as an output:

Filtered array = (
        {
        day = 3;
        hour = 2;
        value = 1;
    },
        {
        day = 3;
        hour = 3;
        value = 0;
    },
        {
        day = 3;
        hour = 4;
        value = 0;
    },
        {
        day = 3;
        hour = 5;
        value = 1;
    },
        {
        day = 3;
        hour = 6;
        value = 0;
    },
        {
        day = 3;
        hour = 7;
        value = 0;
    },
        {
        day = 3;
        hour = 8;
        value = 0;
    },
        {
        day = 3;
        hour = 9;
        value = 1;
    },
        {
        day = 3;
        hour = 11;
        value = 0;
    },
        {
        day = 3;
        hour = 15;
        value = 1;
    },
        {
        day = 4;
        hour = 2;
        value = 1;
    },
        {
        day = 4;
        hour = 3;
        value = 1;
    },
        {
        day = 4;
        hour = 4;
        value = 1;
    },
        {
        day = 4;
        hour = 5;
        value = 1;
    },
        {
        day = 4;
        hour = 6;
        value = 1;
    },
        {
        day = 4;
        hour = 7;
        value = 1;
    },
        {
        day = 4;
        hour = 8;
        value = 0;
    },
        {
        day = 4;
        hour = 9;
        value = 1;
    },
        {
        day = 4;
        hour = 11;
        value = 1;
    },
        {
        day = 4;
        hour = 15;
        value = 1;
    },
        {
        day = 5;
        hour = 2;
        value = 1;
    },
        {
        day = 5;
        hour = 3;
        value = 0;
    },
        {
        day = 5;
        hour = 4;
        value = 1;
    },
        {
        day = 5;
        hour = 5;
        value = 0;
    },
        {
        day = 5;
        hour = 6;
        value = 0;
    },
        {
        day = 5;
        hour = 7;
        value = 1;
    },
        {
        day = 5;
        hour = 8;
        value = 1;
    },
        {
        day = 5;
        hour = 9;
        value = 0;
    },
        {
        day = 5;
        hour = 11;
        value = 0;
    },
        {
        day = 5;
        hour = 15;
        value = 1;
    },
        {
        day = 6;
        hour = 7;
        value = 1;
    },
        {
        day = 6;
        hour = 8;
        value = 1;
    },
        {
        day = 6;
        hour = 22;
        value = 1;
    }
)

https://developer.apple.com/documentation/foundation/nspredicate?language=objc

https://developer.apple.com/documentation/foundation/nscompoundpredicate?language=objc

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html#//apple_ref/doc/uid/TP40001789