4

I have a NSArray of objects. Those objects have an int attribute called "distance". I would like to sort my array by distance.

Could someone please tell me how to do that ? I can't understand how the sortUsingSelector or sortUsingDescriptor methods are working...

Thanks

2 Answers 2

27

I assume you're using an NSMutableArray, because an NSArray is immutable.

When you sort something, you want the end result to be arranged as

x1 <= x2 <= x3 <= x4 <= ... <= xN

How to define this <=? There are 3 solutions in ObjC.


1. -sortUsingSelector:

[arr sortUsingSelector:@selector(foo:)] means that its elements will be compared as*

x <= y      is equivalent to      [x foo:y] <= 0

For example, to sort a list of strings case-insensitively, you use [arr sortUsingSelector:@selector(caseInsensitiveCompare:)].


2. -sortUsingFunction:context:

This is similar to -sortUsingSelector:, but it uses a function pointer as input. [arr sortUsingFunction:funcptr context:ctx] means that its elements will be compared as

x <= y      is equivalent to      funcptr(x, y, ctx) <= 0

3. -sortUsingDescriptors:

This is the most complicated one. It takes a list of NSSortDescriptors which describe the expected order of the properties. One basic example:

NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:desc]];
[desc release];

the descriptor tells the sort routine to "sort by the key distance in ascending order".

Suppose there are 2 keys, integers x ascending then and strings y descending, then you may write

NSSortDescriptor* dx = [[NSSortDescriptor alloc] initWithKey:@"x" ascending:YES];
NSSortDescriptor* dy = [[NSSortDescriptor alloc] initWithKey:@"y" ascending:NO selector:@selector(caseInsensitiveCompare:)];
[arr sortUsingDescriptors:[NSArray arrayWithObjects:x, y, nil]];
[dx release];
[dy release];

and so on.


Note: * Actually you should only return -1, 0 or 1.

Sign up to request clarification or add additional context in comments.

3 Comments

+1, except you don't return -1, 0, or 1. You return NSOrderedDescending, NSOrderedSame, or NSOrderedAscending.
+1, except [NSArray arrayWithObjects:x, y, nil]]; probably should be dx, dy as the objects passed to the array.
What if your array doesnt have distance property, only latitude and longitude and you have a method that calculates distance from userLocation to each lat/long coordinate. What must I do to sort the array then?
3

Finnaly I found out how to do that :

after @implementation :

static NSInteger sort(Myclass *obj1, Myclass *obj2, void *context) {

if(obj1.distance < obj2.distance)
return NSOrderedAscending;
else if(obj1.distance > obj2.distance)
return NSOrderedDescending;
else
return NSOrderedSame;

Then wherever you need to sort your NSArray :

NSArray *sortedArray = [unsortedArray sortedArrayUsingFunction:sort context:NULL];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.