Order array ascending order - iphone

I have an array of objects. On this object is a NSDecimalNumber property distanceFromDevice.
I want to order this array by this property. I have struggled for hours with sorting, anyone got any advice?
- (void)buildSearchableListUsing:(CLLocation *)newLocation
{
listContent = [[NSMutableArray alloc] init];
for(NSAirport *regionalAirport in airportsList)
{
CLLocation *location = [[CLLocation alloc]initWithLatitude:[regionalAirport.latitude doubleValue] longitude:[regionalAirport.longitude doubleValue]];
regionalAirport.distanceFromDevice = [[NSDecimalNumber alloc]initWithDouble:[newLocation distanceFromLocation:location]];
NSLog(#"distanceFromDevice %#", regionalAirport.distanceFromDevice);
[listContent addObject:regionalAirport];
}
//I want listContent ordered by the property distanceFromDevice
}

Try this:
listContent = [[NSMutableArray alloc] init];
NSMutableArray *sortArray = [NSMutableArray array];
for(NSAirport *regionalAirport in airportsList)
{
CLLocation *location = [[CLLocation alloc]initWithLatitude:[regionalAirport.latitude doubleValue] longitude:[regionalAirport.longitude doubleValue]];
regionalAirport.distanceFromDevice = [[NSDecimalNumber alloc]initWithDouble:[newLocation distanceFromLocation:location]];
NSLog(#"distanceFromDevice %#", regionalAirport.distanceFromDevice);
//[listContent addObject:regionalAirport];
[sortArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:regionalAirport,#"arrayElement",regionalAirport.distanceFromDevice,#"elementSorter",nil];
}
[sortArray sortUsingDescriptors:[NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:#"elementSorter" ascending:NO] autorelease]]];
for(NSDictionary *dictionary in sortArray)
{
[listContent addObject:[dictionary valueForKey:#"arrayElement"]];
}

U can sort an NSArray in ascending manner in this way...
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:nil
ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [myArrray sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sortedArray%#",sortedArray);

Related

how to sort an NSArray of float values?

I have an NSArray like this:
how to sort NSarray float with value like this:122.00,45.00,21.01,5.90
#Ron's answer is perfect, but I want to add sorting by using an comparator block. For this trivial case it might be overkill, but it is very handy when it comes to sorting of objects in respect to several properties
NSArray *myArray =[NSArray arrayWithObjects: [NSNumber numberWithFloat:45.0],[NSNumber numberWithFloat:122.0], [NSNumber numberWithFloat:21.01], [NSNumber numberWithFloat:5.9], nil];
NSArray *sortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([obj1 floatValue] > [obj2 floatValue])
return NSOrderedDescending;
else if ([obj1 floatValue] < [obj2 floatValue])
return NSOrderedAscending;
return NSOrderedSame;
}];
try this it work for me
NSArray *array=[[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:12.01],[NSNumber numberWithFloat:13.01],[NSNumber numberWithFloat:10.01],[NSNumber numberWithFloat:2.01],[NSNumber numberWithFloat:1.5],nil];
NSArray *sorted = [array sortedArrayUsingSelector:#selector(compare:)];
Here... use NSSortDescriptor
First Convert the float values into NSNumber
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"floatValue"
ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];
Hope it helps :)

Crazy array sorting in tableView! sortedArrayUsingSelector help?

My tableView app loads the data into the table view.
Everything works perfectly, but the array sorting is kind of messed, like you can see in the picture below. I thought about using the sortedArrayUsingSelector, to straighten things up, but I'm not sure which "sorting method" I should use.
How can I sort this so the cells are sorted according the numbers? Like the order would be 1. 2. 3. 4. 5. etc NOT 1. 10. 11. 12. 13. 14. 2. 3. ?
Thanks a lot in advance!!
And a two-liner:
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES comparator:^(id obj1, id obj2) { return [obj1 compare:obj2 options:NSNumericSearch]; }];
rowTitleArray = [rowTitleArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
Sorry for this convoluted approach, but this does work...
NSArray *rowTitleArray = [[NSArray alloc] initWithObjects:
#"10. Tenth",
#"15. Fifteenth",
#"13. Thirteenth",
#"1. First",
#"2. Second",
#"22. TwentySecond", nil];
NSMutableArray *dictionaryArray = [NSMutableArray array];
for (NSString *original in rowTitleArray) {
NSString *numberString = [[original componentsSeparatedByString:#"."] objectAtIndex:0];
NSNumber *number = [NSNumber numberWithInt:[numberString intValue]];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
number, #"number", original, #"rowTitle", nil];
[dictionaryArray addObject:dict];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"number" ascending:YES];
NSArray *sortedDictionaryArray = [dictionaryArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:descriptor]];
NSMutableArray *sortedRowTitles = [NSMutableArray array];
for (NSDictionary *dict in sortedDictionaryArray) {
[sortedRowTitles addObject:[dict objectForKey:#"rowTitle"]];
}
rowTitleArray = [NSArray arrayWithArray:sortedRowTitles];
NSLog(#"%#", rowTitleArray);
Output:
"1. First",
"2. Second",
"10. Tenth",
"13. Thirteenth",
"15. Fifteenth",
"22. TwentySecond"
I will try to think of a more elegant solution.
Here is a more elegant solution:
NSInteger intSort(id num1, id num2, void *context) {
NSString *n1 = (NSString *) num1;
NSString *n2 = (NSString *) num2;
n1 = [[n1 componentsSeparatedByString:#"."] objectAtIndex:0];
n2 = [[n2 componentsSeparatedByString:#"."] objectAtIndex:0];
if ([n1 intValue] < [n2 intValue]) {
return NSOrderedAscending;
}
else if ([n1 intValue] > [n2 intValue]) {
return NSOrderedDescending;
}
return NSOrderedSame;
}
rowTitleArray = [rowTitleArray sortedArrayUsingFunction:intSort context:NULL];

Objective-c Sort Key array within array

Assuming I have an NSMutableArray which is loaded from file:
searchTermsArray = [[NSMutableArray alloc] initWithContentsOfFile: yourArrayFileName];
inside this array items are key objects
for (int i=0; i<[searchTermsArray count]; i++) {
NSLog(#"for array item %d: %# - %#",i,[[searchTermsArray objectAtIndex:i] objectForKey:#"title"], [[searchTermsArray objectAtIndex:i] objectForKey:#"theCount"] );
}
(which means that each array element (item) has 2 keys values:
searchTermsArray[0] = title (string) , theCount (also a string, but made out of integers)
Question: how should I sort "searchTermsArray" array from higher to lower based on "theCount" value?
(I am looking at the following code but it is not fitting the structure/syntax)
NSSortDescriptor *Sorter = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:NO];
[searchTermsArray sortUsingDescriptors:[NSArray arrayWithObject:Sorter]];
[Sorter release];
Shouldn't you be sorting based on theCount key?
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey:#"theCount" ascending:NO];
[searchTermsArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
I am not sure if there is a better way to do so. But this thing works.
NSInteger intSort(id param1, id param2, void *context) {
NSDictionary *dict1 = (NSDictionary *)param1;
NSDictionary *dict2 = (NSDictionary *)param2;
NSInteger dict1KeyCount = [[dict1 objectForKey:#"count"] intValue];
NSInteger dict2KeyCount = [[dict2 objectForKey:#"count"] intValue];
if (dict1KeyCount < dict2KeyCount) {
return NSOrderedAscending;
}else if (dict1KeyCount > dict2KeyCount) {
return NSOrderedDescending;
}else {
return NSOrderedSame;
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:#"two", #"title", #"2", #"count", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"three", #"title", #"3", #"count", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"one", #"title", #"1", #"count", nil], nil];
NSArray *sortedArray = [array sortedArrayUsingFunction:intSort context:NULL];
for (NSDictionary *dict in sortedArray) {
NSLog(#"%d", [[dict objectForKey:#"count"] intValue]);
}
[super viewDidLoad];
}
The NSSortDescriptor is usually used to sort objects of a class. You pass the name of the property in that class to be compared with others.
Since what you have in your array actually seems to be a NSDictionary, the NSSortDescriptor might not be the best way to approach this problem. Besides, your objects in the dictionary must have a type, so I would try to sort the array myself in one of the classic methods if I were you.

iPhone memory leak and release problem on sorted array

I'm having some troubles with the code below:
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [NSMutableArray arrayWithArray:orderArray];
If I use this code, Instruments says I have a memory leak, why?
Using this code:
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [[NSMutableArray alloc] initWithArray:orderArray];
I receive the leak warning too, however, if I autorelease the object result, a memory error happens.
Here is a better answer I think.
- (NSMutableArray *) orderArray:(NSMutableArray *)array ByKey:(NSString *)key ascending:(BOOL)ascending
{
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending]];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [[[NSMutableArray alloc] initWithArray:orderArray]];
[release idDescriptor];
return [result autorelease];
}
So, you allocate idDescriptor, then you use it, finally release it. Since you're returning result, you can autorelease it with the return. I have one more question though. Do you reference result elsewhere in your code?

crashed on iphone but not on simulator

It is really mind boggling to find out many differences between the iphone and the simulators. I spent several hours trying to figure out why my application ran on the simulator but crashed on my iphone device. It turns out the culprit is sortedArrayUsingDescriptors. Are there more get-you like this? Please share with me.
To share with you on the issue and the fixes:
Code crashed on iphone but not simulator
NSSortDescriptor* aDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
NSArray* anNsArray = [[NSArray alloc] init];
NSArray* aSortedNsArray = [[NSArray alloc] init];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:aDescriptor]];
The issue is on [NSArray arrayWithObject:aDescriptor];
The fixes are to create an Array to store it:
NSArray* descriptorArray = [[NSArray alloc] initWithObjects:countDescrp, nil];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:descriptorArray];
NSSortDescriptor* aDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
NSArray* anNsArray = [[NSArray alloc] init];
NSArray* aSortedNsArray = [[NSArray alloc] init];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:aDescriptor]];
This is a wrong initialization mechanism, and if the code snippet is complete, your problem lies on the anNsArray object that's empty.
You also do not need to initialize the aSortedNsArray.
So it should be:
NSSortDescriptor* sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
// Assume you return it as array of objects from a property or method
NSArray *array = [self objects];
NSArray *sortedArray = nil;
if ([array count] > 0) {
sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
// Then you check the sortedArray
if (sortedArray == nil || [sortedArray count] == 0)
[self somethingIsWrong];
arrayWithObject: (autoreleased) or initWithObject: (manual) is just a different way to allocate NSArray object. It won't cause crashes normally. Because what you care about is the sortedArray not retaining the descriptors array object.