Reputation: 1903
I saw many examples for Custom sort for NSMutableArray , here one of them How to sort an NSMutableArray with custom objects in it?, but I have an object with a and b, and I want to sort them according to a*b.
I saw this code for example
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];
But I do not have birthDate here I need to sort according to a*b (both double)?
More details,
I have a NSMutableArray that contains CGRect objects, and I want to sort them according to width*height
Upvotes: 1
Views: 261
Reputation: 781
I agree with the previous solutions. You can put CGRects in an array by wrapping them into an NSValue:
CGRect rect = CGRectMake(0, 10, 20, 30);
NSValue *valueToPutInArray = [NSValue valueWithCGRect:rect];
and sort them with a block like this:
NSArray *sortedArray = [rectArray sortedArrayUsingComparator:^NSComparisonResult(NSValue *rectAValue, NSValue *rectBValue) {
CGRect rectA = [rectAValue CGRectValue];
CGRect rectB = [rectBValue CGRectValue];
CGFloat areaA = rectA.size.width * rectA.size.height;
CGFloat areaB = rectB.size.width * rectB.size.height;
if (areaA < areaB)
{
return NSOrderedAscending;
}
else if (areaB > areaA)
{
return NSOrderedDescending;
}
else
{
return NSOrderedSame;
}
}];
Another solution would be to wrap the CGRect into a custom object and add a function to it like
- (CGFloat)area
{
return self.rect.size.width * self.rect.size.height;
}
(self.rect is the wrapped rect) If you populate your array with those custom objects you can sort it with your original method by creating a sort descriptor like
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"area" ascending:YES];
This will simply compare the results of the area function and sort the array accruing to that.
Upvotes: 3
Reputation: 92384
The easiest way to implement custom sorting is to use -[NSMutableArray sortUsingComparator:
or -[NSArray sortedArrayUsingComparator:]
.
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
// Compare stuff, return a NSComparisonResult.
return [obj1 compare:obj2];
}];
I like to explicitly pass the object types in the block, BTW. For example, for strings:
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
// Compare stuff, return a NSComparisonResult.
return [obj1 localizedCaseInsensitiveCompare:obj2];
}];
Upvotes: 1
Reputation: 17278
A NSSortDescriptor is not suitable for anything more complex than comparing a simple key, or possibly a set of keys.
You'll want to sort using a custom comparator (a block). Something like
sortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
MyObject *first = (MyObject*)a;
MyObject *second = (MyObject*)b;
if (first.a * first.b < second.a * second.b) {
return NSOrderedAscending;
}
else if (first.a * first.b > second.a * second.b) {
return NSOrderedDescending;
}
return NSOrderedSame;
}]
Note I'm just winging it as far as your (a*b) description goes, not really sure what you want there.
Upvotes: 2