简体   繁体   中英

Subdividng an Array of Core data objects by attribute

I have an array of core data objects that have a time(date) attribute.

What I want to do is place all the core data objects that have the same time into separate arrays and then create an array of those arrays. If no other object has the same time then that object will be in an array by itself.

ie If the array of core data objects had 3 objects with time 08:00 and 1 object with time attribute 09:00 then I want to create one array with the first 3 objects(time 08:00) and a separate array with the last object (time 09:00). Then I want to create an array of those arrays which should be easy enough. Start: [8,8,8,9] Finish: [[8,8,8][9]]

I am struggling most with how to iterate through my original array and pull out all the objects with the same time and then put those objects in their own array.

You can do some thing like this:

  • Add a transient property in your coredata object.
  • Eliminate the minutes and seconds from your date in transient property.
  • Get distinct objects based on your transient property.
  • Filter objects from your main array and add them in a separate array.
  • Finally add them in final array.

Implementation can be like this:

    MyObject *myObject1 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:10*60]];
    MyObject *myObject2 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:10*60]];
    MyObject *myObject3 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:180*60]];
    MyObject *myObject4 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:120*60]];
    MyObject *myObject5 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:120*60]];

    NSMutableArray *myObjects = [NSMutableArray arrayWithObjects:myObject1,myObject2,myObject3,myObject4,myObject5, nil];
    NSArray *distinctObjects = [myObjects valueForKeyPath:@"@distinctUnionOfObjects.transientDate"];
    NSMutableArray *finalArray = [NSMutableArray array];

    for(NSDate *aDate in distinctObjects) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"transientDate == %@", aDate];
        NSArray *filteredArray = [myObjects filteredArrayUsingPredicate:predicate];
        [finalArray addObject:filteredArray];
    }

    NSLog(@"distintobjects: %@", finalArray);

Here is how MyObject looks like:

#import <Foundation/Foundation.h>

@interface MyObject : NSObject
{

}
@property(nonatomic, strong) NSDate *myDate;

@property(nonatomic, strong) NSDate *transientDate;

- (id)initWithDate:(NSDate *)aDate;
@end
#import "MyObject.h"

@implementation MyObject

- (id)initWithDate:(NSDate *)aDate {
    self = [super init];

    self.myDate = aDate;

    return self;
}

- (NSDate *)transientDate {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"dd-MM-yyyy HH"];
    return [dateFormatter dateFromString:[dateFormatter stringFromDate:self.myDate]];
}

- (NSString *)description
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"dd-MM-yyyy HH:mm"];
    return [NSString stringWithFormat:@"transientDate: %@", [dateFormatter stringFromDate:self.transientDate]];
}
@end

Here is the final output: 在此处输入图片说明

One of many ways to do this is using a NSDictionary object where the time is a key and the corresponding object is an array of core data objects that have this time. The core data objects are iterated once.

NSArray *data = core data objects
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (ManagedObjectClass *object in data) {
    NSDate *time = object.time;
    // convert time to time without date
    NSMutableArray *array = dictionary[time];
    if (!array) {
        array = [NSMutableArray array];
        dictionary[time] = array;
    }
    [array addObject:object];
}
NSArray *array = dictionary.allValues;

Another way to do this if the time doesn't need conversion: sort the core data objects by time, iterate the objects, start a new subarray when the time changes and add the object to the subarray.

NSArray *data = core data objects
NSArray *sortedData = [data sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"time" ascending:YES]]];
NSMutableArray *array = [NSMutableArray array];
NSMutableArray *subarray = nil;
NSDate *prevTime = nil;
for (ManagedObjectClass *object in sortedData) {
    NSDate *time = object.time;
    if (![time isEqualToDate:prevTime]) {
        subarray = [NSMutableArray array];
        [array addObject:subarray];
    }
    [subarray addObject:object];
    prevTime = time;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM