Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-25-2010, 12:01 PM   #1 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
Join Date: May 2009
Posts: 49
oohmyygoood is on a distinguished road
Default Sort an NSArray of NSNumber elements

Hi,

I want to sort an NSArray that consists entirely of NSNumber elements.

One would think this would be pretty straight forward and maybe it is, but I'm banging my head against the wall here.

The following code:

Code:
NSNumber intRank;
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"intRank" ascending:YES];
NSArray *mySortedArray = [myArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];
[sorter release];
...causes my app to crash with the following error message:

Quote:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSCFNumber 0x790d940> valueForUndefinedKey:]: this class is not key value coding-compliant for the key intRank.'
What gives?

Any pointers would be highly appreciated. :-)

thx & brgds
oohmyygoood is offline   Reply With Quote
Old 09-25-2010, 02:13 PM   #2 (permalink)
Registered Member
 
Join Date: Aug 2009
Posts: 27
TinyMission is on a distinguished road
Default

Hi, The problem is that there is no relationship between the intRank and the NSNumber. The sorted array works by using a property of the object type within the array as a sort criteria. For instance, if you have an array of Widget objects, and Widget has a property called rank, you could do:

Code:
		NSSortDescriptor *sort = [[[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES] autorelease];
		NSArray *sortDescriptors = [NSArray arrayWithObject:sort];
		NSArray *sortedWidgetArray = [widgetArray sortedArrayUsingDescriptors:sortDescriptors];
I'm not sure if you can use it directly with NSNumber, I never have. I hope this helps...
TinyMission is offline   Reply With Quote
Old 09-26-2010, 02:13 AM   #3 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
Join Date: May 2009
Posts: 49
oohmyygoood is on a distinguished road
Default

Thanks TinyMission!

This put me on the right path:

Quote:
if you have an array of Widget objects, and Widget has a property called rank
If anyone is interested, the way I solved the issue of sorting an NSArray of NSNumber objects, was to create an NSObject subclass called ObjectForSorting with one property only: NSNumber *rank. The ObjectForSorting.h looks like this:

Code:
#import <Foundation/Foundation.h>

@interface ObjectForSorting : NSObject {

	NSNumber *rank;
}

@property (nonatomic, retain) NSNumber *rank;

@end
Make sure you "@synthesize rank;" in ObjectForSorting.m.

Then I created the following method in the class where I wanted to do the sorting:

Code:
- (NSArray *)sortNumberArray:(NSArray *)arrayToSort ascending:(BOOL)ascending {

// Put array of NSNumber objects into array of ObjectForSorting objects

NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:[arrayToSort count]];
	
for (NSNumber *num in arrayToSort) {
	ObjectForSorting *o1 = [[ObjectForSorting alloc] init];
	o1.rank = num;
	[tmpArray addObject:o1];
	[o1 release];
	NSLog(@"->sortNumberArray - BEFORE Sort - num=%i", [num intValue]);
}

// Sort array of ObjectForSorting objects
	
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"rank" ascending:ascending];
NSArray *sortedObjects = [tmpArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];
[sorter release];
[tmpArray release];
	
// Put sorted array of ObjectForSorting objects back into an array of NSNumber objects
	
NSMutableArray *sortedArray = [[NSMutableArray alloc] initWithCapacity:[arrayToSort count]];
	
for (ObjectForSorting *o2 in sortedObjects) {
	NSNumber *num2 = [[NSNumber alloc] init]; 
	num2 = o2.rank;
	[sortedArray addObject:num2];
	[num2 release];
	NSLog(@"->sortNumberArray - AFTER Sort - num=%i", [num2 intValue]);
}
	
NSArray *returnArray = [NSArray arrayWithArray:sortedArray];
[sortedArray release];
	
return returnArray;
	
}
There may be a more elegant way of doing this, but at least it works. :-)

thx & brgds
oohmyygoood is offline   Reply With Quote
Old 10-25-2010, 05:53 AM   #4 (permalink)
Ankur
 
Join Date: Jun 2010
Posts: 21
ankur.s20 is on a distinguished road
Default Sorting NSNumber array

Though this reply is too late but Alternatively you can try the following:
Let's assume you already prepared an NSArray "arrayToBeSorted" with NSNumber objects which contain float Values:

NSSortDescriptor *mySorter = [[NSSortDescriptor alloc] initWithKey:@"floatValue" ascending:YES];
[arrayToBeSorted sortUsingDescriptors:[NSArray arrayWithObject:mySorter]];

Similarly you can have NSArray of int to get it Sorted using key intValue.
ankur.s20 is offline   Reply With Quote
Old 09-10-2011, 03:34 PM   #5 (permalink)
Registered Member
 
Join Date: Sep 2009
Location: Germany
Posts: 36
Rikco is on a distinguished road
Default

Quote:
Originally Posted by ankur.s20 View Post
Though this reply is too late but Alternatively you can try the following:
Let's assume you already prepared an NSArray "arrayToBeSorted" with NSNumber objects which contain float Values:

NSSortDescriptor *mySorter = [[NSSortDescriptor alloc] initWithKey:@"floatValue" ascending:YES];
[arrayToBeSorted sortUsingDescriptors:[NSArray arrayWithObject:mySorter]];

Similarly you can have NSArray of int to get it Sorted using key intValue.
thanks, exactly what I was searching for!
Rikco is offline   Reply With Quote
Old 09-10-2011, 05:01 PM   #6 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by Rikco View Post
thanks, exactly what I was searching for!
There are lots of ways to skin this cat.

You can also use the method sortUsingSelector to sort objects like NSNumbers that have a compare method:


Code:
[theArray sortUsingSelector: @selector(compare:)];
or to create a new, sorted version of the array:

Code:
NSArray* sortedArray = [theArray sortedArrayUsingSelector: @selector(compare:)];

There are also the new code block based sort methods like sortedArrayUsingComparator: that let you provide a code block to do the comparison. That can be useful for sorting arrays of objects that don't have a compare method.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 03-02-2012, 07:43 AM   #7 (permalink)
FlexJunkie switching over
 
Join Date: Feb 2012
Location: Leuven, Belgium
Age: 22
Posts: 25
peterver is on a distinguished road
Default

or you could write your own sort function : ]

Code:
-(NSMutableArray *) bubble_sort:(NSMutableArray *) arr_source {
    if([arr_source count] <= 1) {
        return arr_source;
    }
    int i;
    int j;
    int length = [arr_source count];
    location *l_1;
    location *l_2;
    
    NSMutableArray *tmp_source = [[NSMutableArray alloc] init];
    
    for(j = 0; j < length; j++) {
        for(i = 1; i < length - j; i++) {
            l_1 = (location *)[arr_source objectAtIndex:i-1];
            l_2 = (location *)[arr_source objectAtIndex:i];
            if(l_1.cld < l_2.cld) {
                [tmp_source addObject:l_1];
                [tmp_source addObject:l_2];
            } else {
                [tmp_source addObject:l_2];
                [tmp_source addObject:l_1];
            }
        }
    }
    
    return tmp_source;
}
peterver is offline   Reply With Quote
Old 03-02-2012, 08:59 AM   #8 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default That's a bubble sort

Quote:
Originally Posted by peterver View Post
or you could write your own sort function : ]

Code:
-(NSMutableArray *) bubble_sort:(NSMutableArray *) arr_source {
    if([arr_source count] <= 1) {
        return arr_source;
    }
    int i;
    int j;
    int length = [arr_source count];
    location *l_1;
    location *l_2;
    
    NSMutableArray *tmp_source = [[NSMutableArray alloc] init];
    
    for(j = 0; j < length; j++) {
        for(i = 1; i < length - j; i++) {
            l_1 = (location *)[arr_source objectAtIndex:i-1];
            l_2 = (location *)[arr_source objectAtIndex:i];
            if(l_1.cld < l_2.cld) {
                [tmp_source addObject:l_1];
                [tmp_source addObject:l_2];
            } else {
                [tmp_source addObject:l_2];
                [tmp_source addObject:l_1];
            }
        }
    }
    
    return tmp_source;
}
Sure, you can write your own sort code. However, the code you posted is a bubble sort, which is a "naive" sort with terrible performance. Its run-time goes up with the square of the number of elements being sorted, which is VERY bad. Try that code on an array of 10,000 strings and see what happens. It will take a long, long time.

For less than 100 elements, is is usable, but beyond that it gets too slow REALLY fast.

I dare say the system sort methods use shell-Metzler, QuickSort, or some other more efficient sort routine.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 03-05-2012, 02:27 AM   #9 (permalink)
FlexJunkie switching over
 
Join Date: Feb 2012
Location: Leuven, Belgium
Age: 22
Posts: 25
peterver is on a distinguished road
Default

duncan you're completely right on the subject of bubble sort performance. However this was just a simple example. I sometimes find it better to explain something with a small bit of sample code.

The true thing that worries me is that for a simple thing such as sorting an array of numbers developers are asking help :/. Even if you don't find a certain (probably) built-in function right of the bat, it's probably best to write your own function instead of searching through the documentation for hours upon hours :/. A bubble sort is simple because you can easily write your own in less than 5 minutes. If by any chance the performance might prove to be an issue then you have sound grounds to look for a better solution.

i apologize if this reply sounded crude.
peterver is offline   Reply With Quote
Old 03-05-2012, 10:26 AM   #10 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by peterver View Post
duncan you're completely right on the subject of bubble sort performance. However this was just a simple example. I sometimes find it better to explain something with a small bit of sample code.

The true thing that worries me is that for a simple thing such as sorting an array of numbers developers are asking help :/. Even if you don't find a certain (probably) built-in function right of the bat, it's probably best to write your own function instead of searching through the documentation for hours upon hours :/. A bubble sort is simple because you can easily write your own in less than 5 minutes. If by any chance the performance might prove to be an issue then you have sound grounds to look for a better solution.

i apologize if this reply sounded crude.

I'm mixed on this. On the one hand, I agree with you that its scary how people go running to the forums looking for ready-made solutions to every little problem they face.

On the other hand, sorting is actually a pretty deep subject. There are whole books written on the subject, and good sorting algorithms are not easy to write.

Yes you can write a bubble sort in less than 5 minutes, but it can take tens of minutes to sort moderate-sized arrays, where a faster sort could be done in seconds. It doesn't take long for an N squared algorithm to become unacceptably slow.

I don't think you did anybody any favors by posting a bubble sort without qualifying it as a naive sort algorithm with really, really bad performance.

Remember, a lot of utter newbies read this forum, and cut-and-paste code they find into their projects, not understanding at all what they are doing. If you don't say "Here's some simple sort code to show how it's done. You should not use this code except to sort very short lists, as it will be VERY, VERY slow."

One of the major plusses in using Apple's built-in sort methods is that they can use robust, fast, debugged sort code, and all you have to do is to provide a comparison method/block/selector. The sort method can use very sophisticated algorithms, and even adaptive logic that chooses the algorithm based on the number of items.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 03-10-2012, 09:42 AM   #11 (permalink)
FlexJunkie switching over
 
Join Date: Feb 2012
Location: Leuven, Belgium
Age: 22
Posts: 25
peterver is on a distinguished road
Default

you're completely right .

I'll take note of that in the future.
peterver is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 344
9 members and 335 guests
2ndSegment, headkaze, mistergreen2011, nobstudio, Objective Zero, pungs, revg, v1n2e7t
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,655
Threads: 94,116
Posts: 402,889
Top Poster: BrianSlick (7,990)
Welcome to our newest member, pungs
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 11:07 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0