Rebuild an NSArray by grouping objects that have matching id numbers?
NSArray *array = @[@{@"groupId" : @"1", @"name" : @"matt"},
@{@"groupId" : @"2", @"name" : @"john"},
@{@"groupId" : @"3", @"name" : @"steve"},
@{@"groupId" : @"4", @"name" : @"alice"},
@{@"groupId" : @"1", @"name" : @"bill"},
@{@"groupId" : @"2", @"name" : @"bob"},
@{@"groupId" : @"3", @"name" : @"jack"},
@{@"groupId" : @"4", @"name" : @"dan"},
@{@"groupId" : @"1", @"name" : @"kevin"},
@{@"groupId" : @"2", @"name" : @"mike"},
@{@"groupId" : @"3", @"name" : @"daniel"},
];
NSMutableArray *resultArray = [NSMutableArray new];
NSArray *groups = [array valueForKeyPath:@"@distinctUnionOfObjects.groupId"];
for (NSString *groupId in groups)
{
NSMutableDictionary *entry = [NSMutableDictionary new];
[entry setObject:groupId forKey:@"groupId"];
NSArray *groupNames = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"groupId = %@", groupId]];
for (int i = 0; i < groupNames.count; i++)
{
NSString *name = [[groupNames objectAtIndex:i] objectForKey:@"name"];
[entry setObject:name forKey:[NSString stringWithFormat:@"name%d", i + 1]];
}
[resultArray addObject:entry];
}
NSLog(@"%@", resultArray);
Output:
(
{
groupId = 3;
name1 = steve;
name2 = jack;
name3 = daniel;
},
{
groupId = 4;
name1 = alice;
name2 = dan;
},
{
groupId = 1;
name1 = matt;
name2 = bill;
name3 = kevin;
},
{
groupId = 2;
name1 = john;
name2 = bob;
name3 = mike;
}
)
Add objects to NSMutable array with grouping
Okay, so you have an array of items, and you want to group them into sections based on a particular key.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MM/dd/yyyy"];
// Sparse dictionary, containing keys for "days with posts"
NSMutableDictionary *daysWithPosts = [NSMutableDictionary dictionary];
[myPosts enumerateObjectsUsingBlock:^(PFObject *object, NSUInteger idx, BOOL *stop) {
NSString *dateString = [formatter stringFromDate:[object createdAt]];
// Check to see if we have a day already.
NSMutableArray *posts = [daysWithPosts objectForKey: dateString];
// If not, create it
if (posts == nil || (id)posts == [NSNull null])
{
posts = [NSMutableArray arrayWithCapacity:1];
[daysWithPosts setObject:posts forKey: dateString];
}
// add post to day
[posts addObject:obj];
}];
// Sort Dictionary Keys by Date
NSArray *unsortedSectionTitles = [daysWithPosts allKeys];
NSArray *sortedSectionTitles = [unsortedSectionTitles sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDate *date1 = [formatter dateFromString:obj1];
NSDate *date2 = [formatter dateFromString:obj2];
return [date2 compare:date1];
}];
NSMutableArray *sortedData = [NSMutableArray arrayWithCapacity:sortedSectionTitles.count];
// Put Data into correct format:
[sortedSectionTitles enumerateObjectsUsingBlock:^(NSString *dateString, NSUInteger idx, BOOL *stop) {
NSArray *group = daysWithPosts[dateString];
NSDictionary *dictionary = @{ @"date":dateString,
@"group":group };
[sortedData addObject:dictionary];
}];
self.sampleData = sortedData;
This code will not generate exactly what you asked for. It will generate something that looks like this:
sampleData = @[ @{ @"date": @"12/5/2014",
@"group": @@[ PFObject*,
PFObject*,
PFObject*,
PFObject*,
PFObject*,
]
},
@{ @"date": @"12/3/2014",
@"group": @[ PFObject*,
PFObject*,
PFObject*,
PFObject*,
PFObject
]
}
];
There's no need to convert your PFObject*
in the myPosts
array into @{ @"text": @"post5", @"location": @"x,y" }
since you'll lose access to other pieces of information. Here is how you would use this sampleData
array.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; {
return self.sampleData.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; {
return self.sampleData[section][@"date"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; {
return self.sampleData[section][@"group"].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; {
PFObject *post = self.sampleData[indexPath.section][@"group"][indexPath.row];
UITableViewCell *cell = // dequeue A reusable tableviewcell here
// configure the cell here
return cell;
}
How to implement group by values in NSMutableArray?
Shanti's answer is close. You want to use the Key-Value Coding collection operator @distinctUnionOfObjects
. Place the operator immediately preceding the key which you want it to affect, as if it is a part of the key path you are accessing:
[logMuArray valueForKeyPath:@"@distinctUnionOfObjects.log_date"]
Notice the use of valueForKeyPath:
, not valueForKey:
The former is a method in the Key-Value Coding protocol, and allows accessing arbitrary depth of attributes. The key path is an NSString
made up of dot-separated keys. The result of each key lookup is used in turn to access the next key (starting with the original receiver); by default, valueForKey:
is simply called at each step.
iOS how to place header in collection view of date between photos as in iPhone photos app
NSArray<PHAsset *> *imageAssets = @[];
NSMutableDictionary<NSString *, NSMutableArray *> *groupedAssets = [NSMutableDictionary dictionary];
for (PHAsset *imageAsset in imageAssets) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MMM dd, yyyy"];
NSString *key = [dateFormatter stringFromDate:imageAsset.creationDate];
// Add asset to group
NSMutableArray *group = [groupedAssets objectForKey:key];
if (!group) {
group = [NSMutableArray array];
[groupedAssets setObject:group forKey:key];
}
[group addObject:imageAsset];
}
This is an idea about how can you approach your problem. Above code assumes that you have an array of PHAssets. The groupedAssets object you receive at the end of the loop is collection of assets grouped by day.
Related Topics
Once Jailbroken, Will iOS Apps Run with Root Privilege
Detecting iPhone 6/6+ Screen Sizes in Point Values
Using Custom Font in a Uiwebview
How to Prompt the User to Turn on Location Services After User Has Denied Their Use
How to Hide/Show Tab Bar of a View with a Navigation Bar in iOS
How to Embed a Youtube Video into My App
Does Swift Support Implicit Conversion
Detect iOS Application About to Delete
Convert Nsdata to Sockaddr Struct in Swift
How to Debug "Terminated Due to Memory Error"
In Firebase, How to Query the Most Recent 10 Child Nodes
App Installation Failed Due to Application-Identifier Entitlement
Difference Between _ and Self. in Objective-C
How to Remove Cache in Wkwebview
Screenshot for Avplayer and Video
What Describes the Application Delegate Best? How Does It Fit into the Whole Concept