views:

258

answers:

3

I have an array of objects that i want to sort by two keys. The objects lets say are of type Student and the properties that i'm intrested in for my sort are grade and name.

Student
{
    double grade;
    string name;
    ...
} 

How can i sort the objects first by grade and then by name? so for example if i have the list: Tom 9.9 Andrew 9.8 Chriestie 10 Mat 9.8 Allison 10 Ada 9.8

After the sort i should have: Allison 10 Christie 10 Tom 9.9 Ada 9.8 Andrew 9.8 Mat 9.8

And not Christie 10 Allison 10 Tom 9.9 Andrew 9.8 Ada 9.8 Mat 9.8

any pointer is really helpful.

+2  A: 

You basically need to implement your own comparator and use one of NSArray sort methods (e.g. sortedArrayUsingSelector:)

-(NSComparisonResult)compare:(Student *)student {
  // sort by name
  int nameComp = [name compare:student.name];
  if (nameComp != NSOrderedSame) return nameComp;

  // reverse ordered as desired in the question
  if (grade > student.grade)
    return NSOrderedAscending;
  else if (grade == student.grade) // watchout here
    return NSOrderedSame;
  else
    return NSOrderedDescending;
}

NSArray *unsrtedArray = ...
NSArray *sortedArray = [unsortedArray sortedArrayUsingSelector:@selector(compare:)];
notnoop
i will try it. thank you!
SorinA.
A: 

I can't really help you with the code - as I don't know objective-c, but if I were going to implement my own multiple sort (I'm a .Net programmer and we have lots of shortcuts for this), then I'd do it as follows:

  • Sort the set by the last criteria and produce lists as the result. Each item in each list has the same value that was being sorted. So from your list you end up with (depending on the order):

    List 1: (10.0 score) Christie, Allison List 2: (9.9 score) Tom List 3: (9.8 score) Andrew, Mat, Ada

  • Now, move through the list of lists and sort those according to the first criteria. Which will then sort your people by their names, keeping their order with respect to scroe the same.

Noe you can produce your sorted list by simply running through the list of lists in left-right order, adding each element into an output list.

A bit 'list' heavy this, sorry; and apologies for not knowing objective-c - it's entirely possible that there are already helper classes built into it that can simplify this for you - I know that C's STL does.

Andras Zoltan
no apologies needed, thank you for the idea!
SorinA.
+3  A: 

I'm pretty flakey on my objective-c knowledge but there's some good pointers here and there's always the documentation. Here's my crack at it...

NSSortDescriptor *gradeSorter = [[NSSortDescriptor alloc] initWithKey:@"grade" ascending:YES];
NSSortDescriptor *nameSorter = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

[personList sortUsingDescriptors:[NSArray arrayWithObjects:gradeSorter, nameSorter, nil]];
Ajw
This is the easiest way to do it in my opinion. Sorting using sort descriptors allows you to achieve any level of hierarchical sorting. i.e., all objects are sorted according to the first sort descriptor, any remaining duplicates are sorted according to the second third descriptor, and so on. If you want, see http://github.com/LucasTizma/spot_trot_helpers#nsarray+stadditions for my category on `NSArray` (`NSArray+STAdditions`) that helps consolidate the syntax for using sort descriptors.
LucasTizma