setting multiple sort descriptors - ios

I have a array of objects and need to sort it by rating and after by number of votes descendent(so that if two 5 stars rated elements compare, the one with the most votes should be first)
Is it possible to sort a NSArray by two descriptors:first after rating and then after votes count?
I've found on http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSSortDescriptor_Class/Reference/Reference.html
something like sortUsingDescriptors: but i can't find it anywhere in the docs, think it's deprecated.

Yes you can:
NSSortDescriptor *sortRating = [[NSSortDescriptor alloc] initWithKey:#"rating" ascending:NO];
NSSortDescriptor *sortVotes = [[NSSortDescriptor alloc] initWithKey:#"votes" ascending:NO];
NSArray *sortedArray = [orignalAray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortRating, sortVotes, nil]];
[sortRating release], sortRating = nil;
[sortVotes release], sortVotes = nil;

You are basically right. On NSArray there is the
- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors
method. This will return a new array, sorted according to various descriptors.
- (void)sortUsingDescriptors:(NSArray *)sortDescriptors
does exist, but is on NSMutableArray, which might explain why you couldn't find it in the documentation for NSArray. It accomplishes the same goal, but sorts the array you call it on, rather than returning a new array. Neither is deprecated.

Here's a one-liner.
NSArray *sortedArray = [unsortedArray sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey#"rating" ascending:NO], [NSSortDescriptor sortDescriptorWithKey#"date" ascending:NO], nil]];

Use - (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors. Here is the documentation: NSArray Class Reference
E.g:
NSSortDescriptor *sortRating = nil;
NSSortDescriptor *sortDate = nil;
NSSortDescriptor *sortRating = [[NSSortDescriptor alloc] initWithKey:#"rating" ascending:NO];
NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:NO];
NSArray *sortedArray = [auxArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortRating,sortDate,nil]];
[sortRating release];
sortRating = nil;
[sortDate release];
sortDate = nil;
Cheers!

If you have one NSArray use this one:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"x_date" ascending:TRUE];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"x_time" ascending:TRUE];
[tempArray sortUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor,sortDescriptor1, nil]];

Related

Use Two NSSortDescriptor to filter array

I would like to sort an array using the dictionary values "Name" and "Count". It would be Name alphabetically and split the names up into two groupd based on count.
bigger than 0
Smaller than Equal 0
My current implementation looks like this however it dose not split the groups up correctly.
NSSortDescriptor *sortCountDescriptor = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
NSSortDescriptor *sortNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObjects:sortCountDescriptor, sortNameDescriptor, nil];
NSArray *sortedArray = [myArrayToSort sortedArrayUsingDescriptors:sortDescriptors];
return [sortedArray mutableCopy];
If by grouping you mean making them separate arrays then you need an NSPredicate instead of NSSortDescriptor for count key.
Try this (from what I understood the array is filled with instances of NSDictionary so I used casting to it. If that assumption is incorrect, the NSPredicate isn't hard to change to some other type or to be made more generic with KVC):
NSSortDescriptor *sortNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSArray * sortDescriptors = [NSArray arrayWithObjects:sortNameDescriptor, nil];
NSArray *sortedArray = [myArrayToSort sortedArrayUsingDescriptors:#[sortNameDescriptor]];
NSPredicate *zeroOrLessPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
if ([[((NSDictionary*)evaluatedObject) objectForKey:#"count"] integerValue] <= 0) {
return YES;
}
else {
return NO;
}
}];
NSArray *zeroOrLessArray = [sortedArray filteredArrayUsingPredicate:zeroOrLessPredicate];
NSPredicate *moreThanZeroPredicate = [NSCompoundPredicate notPredicateWithSubpredicate:zeroOrLessPredicate];
NSArray *moreThanZeroArray = [sortedArray filteredArrayUsingPredicate:moreThanZeroPredicate];

How to sort array of dictionaries by date using sort descriptor

I have an array of dictionaries where dictionary is like this.
Rows = (
"<DriverRowRecord: 0x7f8de3a240d0>",
"<DriverRowRecord: 0x7f8de3a18790>"
);
Sections = "<DriverSectionRecord: 0x7f8de3a2c5a0>";
Here DriverRowRecord and DriverSectionRecord are separate classes. In DriverSectionRecord I have a date property.
#interface DriverSectionRecord : NSObject
#property(nonatomic,retain)NSDate *date;
#end
Now I want to sort the array based on DriverSectionRecord's date property. If the dictionary contains the date key I sort it like this.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:descriptor];
NSArray *Ascendingorder = [Array sortedArrayUsingDescriptors:descriptors];
However, it doesn't work as date is a property of DriverSectionRecord. How can I achieve this?
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"Sections.date" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:descriptor];
NSArray *Ascendingorder = [Array sortedArrayUsingDescriptors:descriptors];
I got he solution from above comments. Thanks to all for such a great clarification.

Sorting NSMutableArray with custom class by date

I have NSMutableArray named "allConversations" that contains a custom class "Users".
every user have property "lastMessageDate".
e.x : user.lastMessageDate;
what is the best way to sort the array by date?
I have this code :
NSMutableArray *arrCopy = [[NSMutableArray alloc]initWithArray:unSortedArr];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lastMessageDate" ascending:TRUE];
[arrCopy sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
but I don't know how to implement it in this situation
it seems all you are missing is the assignment. This should work for you.
arrCopy = [arrCopy sortedArrayUsingDescriptors:#[[[NSSortDescriptor alloc] initWithKey:#"createdAt" ascending:YES]]];

Sort NSMutableArray of PFObjects by creationDate

How would I sort an array of PFObjects by their creationDate? I've tried something like the following, but this does not produce the desired result.
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"creationDate"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray
sortedArrayUsingDescriptors:sortDescriptors];
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"createdAt"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray
sortedArrayUsingDescriptors:sortDescriptors];
Or alternatively updatedAt for last updated.
Change dateDescriptor to:
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"self.creationDate"
ascending:YES];
You need to add self if you want to check properties in objects inside the array.

Sort NSArray of NSDictionaries ignore case

I am sorting an NSArray of NSDictionaries which is working using the following code
NSArray *getIndexArray = [nicknamesCombinedArray copy];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"MANUFACTURER" ascending:YES];
NSDictionary *sortedGetIndexArray = [getIndexArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
The only issue is that when it sorts if the word is all CAPS then it sorts like this
JESS
Jack
Jelly
Job
Where I would like it to be
Jack
Jelly
JESS
Job
Try this code..
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"MANUFACTURER" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];

Resources