What I want to do seems pretty simple, but I can\'t find any answers on the web. I have an NSMutableArray
of objects, and let\'s say they are \'Person\' objects
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];
NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];
[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];
NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];
ForeignStockHolding *stockHoldingCompany;
NSLog(@"Fortune 6 companies sorted by Company Name");
while (stockHoldingCompany = [enumerator nextObject]) {
NSLog(@"===============================");
NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
}
NSLog(@"===============================");
See the NSMutableArray
method sortUsingFunction:context:
You will need to set up a compare function which takes two objects (of type Person
, since you are comparing two Person
objects) and a context parameter.
The two objects are just instances of Person
. The third object is a string, e.g. @"birthDate".
This function returns an NSComparisonResult
: It returns NSOrderedAscending
if PersonA.birthDate
< PersonB.birthDate
. It will return NSOrderedDescending
if PersonA.birthDate
> PersonB.birthDate
. Finally, it will return NSOrderedSame
if PersonA.birthDate
== PersonB.birthDate
.
This is rough pseudocode; you will need to flesh out what it means for one date to be "less", "more" or "equal" to another date (such as comparing seconds-since-epoch etc.):
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
if ([firstPerson birthDate] < [secondPerson birthDate])
return NSOrderedAscending;
else if ([firstPerson birthDate] > [secondPerson birthDate])
return NSOrderedDescending;
else
return NSOrderedSame;
}
If you want something more compact, you can use ternary operators:
NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}
Inlining could perhaps speed this up a little, if you do this a lot.
Your Person
objects need to implement a method, say compare:
which takes another Person
object, and return NSComparisonResult
according to the relationship between the 2 objects.
Then you would call sortedArrayUsingSelector:
with @selector(compare:)
and it should be done.
There are other ways, but as far as I know there is no Cocoa-equiv of the Comparable
interface. Using sortedArrayUsingSelector:
is probably the most painless way to do it.
I just done multi level sorting based on custom requirement.
//sort the values
[arrItem sortUsingComparator:^NSComparisonResult (id a, id b){
ItemDetail * itemA = (ItemDetail*)a;
ItemDetail* itemB =(ItemDetail*)b;
//item price are same
if (itemA.m_price.m_selling== itemB.m_price.m_selling) {
NSComparisonResult result= [itemA.m_itemName compare:itemB.m_itemName];
//if item names are same, then monogramminginfo has to come before the non monograme item
if (result==NSOrderedSame) {
if (itemA.m_monogrammingInfo) {
return NSOrderedAscending;
}else{
return NSOrderedDescending;
}
}
return result;
}
//asscending order
return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];
https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];
Thanks, it's working fine...
I've used sortUsingFunction:: in some of my projects:
int SortPlays(id a, id b, void* context)
{
Play* p1 = a;
Play* p2 = b;
if (p1.score<p2.score)
return NSOrderedDescending;
else if (p1.score>p2.score)
return NSOrderedAscending;
return NSOrderedSame;
}
...
[validPlays sortUsingFunction:SortPlays context:nil];