开发者

NSMutableArray Sort Using Selector

I have googled, searched stackoverflow without satisfying answers.

In the documentation, it states that:

sortUsingSelector: Sorts the array’s elements in ascending order, as determined by the comparison method specified by a given selector.

  • (void)sortUsingSelector:(SEL)comparator Parameters comparator A selector that specifies the comparison method to use to compare elements in the array. The comparator message is sent to each object in the array and has as its single argument another object in the array. The comparator method should return NSOrderedAscending if the array is smaller than the argument, NSOrderedDescending if the array is larger than the argument, and NSOrderedSame if they are equal.

I'm trying to understand how it really works. So if I have this method in my object within array class:

- (NSComparisonResult) compareNames: (id) element
{
    return [userName compare: [element userName]];
}

And execute it with

[myArray sortUsingSelector:@selector(compareNames:);
开发者_如何学Python

It works. The problem is I don't know why it works. The return type for NSComparisonResult are either Ascending, Same, or Descending. From what I get by reading documentation is the compareNames method is sent to every object in the myArray and compare the selected object property (in this case is userName) with the userName in another object within the same array. (Like the [0] array is compared to the [1] array). I want to know how this whole process is going.

Update 1: Sorting Algorithm for Multiple Keys

I missed the ! in the comparison. It should be right like this:

NSComparisonResult res;
res = [[self userName] compare: [element userName]];
if(res == NSOrderedSame) res = [[self email] compare: [element email]];
return res;

As for sorting into descending, you can use switch or if to revert the NSComparisonResult value by replacing "return res" with this:

switch (res)
    {
        case NSOrderedAscending:
            return NSOrderedDescending;
            break;
        case NSOrderedDescending :
            return NSOrderedAscending;
            break;
        default:
            return NSOrderedSame;
            break;
    }*/


To answer your subquestions in the comments:

Does sorting always need to be Ascending? - NSOrderedAscending & NSOrderedDescending are just symbolic here, you might better think of them as "object comes before argument" and "object comes after argument" in the sort order. E.g. if you are storing an array of NSNumber then "1 compareTo:2" should return NSOrderedAscending if you want to sort with increasing value, and NSOrderedDescending if you want to sort with decreasing value.

How do you sort with multiple keys? - Any sorting algorithm only needs to know if one item comes before, after, or at the same position as another. How you determine that is up to you. To use two sort keys then in pseudo-code the algorithm is:

To compare item1 and item2
    order = [item1.key1 compareTo:item2.key1];
    if (order == NSOrderedSame) order = [item1.key2 compareTo:item2.key2];
    return order

Extend to more keys or more complex comparisons as needed.


Followup to comment:

Sorry, but the supplied algorithm does do a 2 key sort, and in general combining the keys may not and is wasteful.

In English sorting by two keys goes as follows: first compare the first key of each object, if they compare not equal then return their ordering. If they compare equal then move on and compared the second key of each object and return their ordering.

This is exactly what the pseudo code above does.

Combining multiple keys is problematic for a number of reasons:

  1. You must combine them using a separator which cannot occur in the keys. As a simple example consider sorting by given name, family name when you have the two people "jack yolander" and "jacky olander" - a naive joining produces "jackyolander" for both and they would sort equal. So you need a separator which cannot occur in any of the keys.

  2. If the keys are of different types, e.g. a string and a number, you end up converting them all to strings to combine - wasteful and maybe even inaccurate.

  3. Simply combining them is wasteful - you are generating objects you don't need.

Etc. Just compare the keys in pairs until you either find two which differ or get to the last pair. Works for any number of keys, of any types, and isn't wasteful.


sortUsingSelector will be using Quicksort or a similar sorting algorithm to sort the array. Sorting algorithms need to be able to compare two items in the collection to be sorted and determine where they should appear relative to each other in sorted order. Should A appear before B, after B or immediately alongside it? Your custom sort method (compareNames in your example) is all the sorting algorithm needs to determine that ordering.

Have a look at the Wikipedia entry for sorting algorithms for some background on this.

You won't find much online about this if you search for e.g. "sortUsingSelector". This isn't an Objective-C-specific issue, pretty much all programming languages have sort routines that use a user-defined comparison function to do the sorting.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜