How to sort the array in Objective C? [duplicate] - iphone

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to sort array having numbers as string in iPhone?
How Do I sort an NSMutable Array with NSNumbers in it?
I have a NSMutableArray with random order of numbers. I have to sort them in ascending and descending order? Is there any in built function for that and if no how it can be done. Array is like this:
arr = ["12","85","65","73","21","87","1","34","32"];

Sorting NSMutableArray (based on key) which contains objects
First, you’ll need to create an NSSortDescriptor and tell it which key to sort the array on.
NSSortDescriptor *lastNameSorter = [[NSSortDescriptor alloc] initWithKey:#"lastName" ascending:YES];
[personList sortUsingDescriptors:[NSArray arrayWithObject:lastNameSorter]];
Hope this Full tutorial helps you.

use sortUsingSelector instance method of class NSMutableArray.
use this line (But you need to use NSNumbers rather than string in case of numbers)
[myArray sortUsingSelector:#selector(compare:)];
It sort array in ascending order. for descending order add this line after above line.
myArray=[myArray reverseObjectEnumerator] allObjects];

example code for your case:
NSArray *sortedArray;
sortedArray = [anArray sortedArrayUsingFunction:intSort context:NULL];
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
you can develop a logic to sort your array in intsort method and pass it as parameter to above method.
there are many predefined methods like:
sortUsingDescriptors:
sortUsingComparator:
sortWithOptions:usingComparator:
sortUsingFunction:context:
sortUsingSelector:
follow developer.apple.com for api
good luck TNX

Related

How can I get all the possibles combinations of numbers from an array in Objective-C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generating permutations of NSArray elements
Let's say that I have
[1,2]
And I want to get
{1}
{2}
{1, 2}
{2, 3}
I think the name of the thing you're looking for is 'power set'. It sounded fun, so here's a crack at it. I relied on this very concise article for the algorithm. I'm not sure if this is efficient (...actually, I'm sure this is inefficient) over large sets.
// answer the powerset of array: an array of all possible subarrays of the passed array
- (NSArray *)powerSet:(NSArray *)array {
NSInteger length = array.count;
if (length == 0) return [NSArray arrayWithObject:[NSArray array]];
// get an object from the array and the array without that object
id lastObject = [array lastObject];
NSArray *arrayLessOne = [array subarrayWithRange:NSMakeRange(0,length-1)];
// compute the powerset of the array without that object
// recursion makes me happy
NSArray *powerSetLessOne = [self powerSet:arrayLessOne];
// powerset is the union of the powerSetLessOne and powerSetLessOne where
// each element is unioned with the removed element
NSMutableArray *powerset = [NSMutableArray arrayWithArray:powerSetLessOne];
// add the removed object to every element of the recursive power set
for (NSArray *lessOneElement in powerSetLessOne) {
[powerset addObject:[lessOneElement arrayByAddingObject:lastObject]];
}
return [NSArray arrayWithArray:powerset];
}
If you think this is a keeper, you could make it a category method on array and drop the parameter. Test it like this...
NSLog(#"empty = %#", [self powerSet:[NSArray array]]);
NSLog(#"one item = %#", [self powerSet:[NSArray arrayWithObject:#"a"]]);
NSLog(#"two items = %#", [self powerSet:[NSArray arrayWithObjects:#"a", #"b", nil]]);
NSLog(#"three items = %#", [self powerSet:[NSArray arrayWithObjects:#"a", #"b", #"c", nil]]);
I did only these tests, and the output looked good. Spoiler alert: the three item test looks roughly like this on my console (with \n's removed):
three items = ((),
(a),
(b),
(a,b),
(c),
(a,c),
(b,c),
(a,b,c))

Sort an NSArray in Descending Order

I have an NSArray of NSNumber objects that I have successfully sorted in ascending order using the following:
[myArray sortedArrayUsingSelector:#selector(compare:)]
However, I need to sort this in descending order. I take it that compare: only sorts in ascending order. While I can go about reversing the NSArray, I am curious as to whether or not there is a more simpler or more effective way of going about doing this.
EDIT: I found this question which provides a simple way to reverse iterate an NSArray:
for (id someObject in [myArray reverseObjectEnumerator])
This works fine, I guess it's a nice simple solution, but I'm curious as to whether or not there is a way to specify sorting in descending order.
Use a sort descriptor
NSSortDescriptor* sortOrder = [NSSortDescriptor sortDescriptorWithKey: #"self"
ascending: NO];
return [myArray sortedArrayUsingDescriptors: [NSArray arrayWithObject: sortOrder]];
Another way, imo, is also nice: write another reverseCompare with category:
#implementation NSNumber (Utility)
- (NSComparisonResult)reverseCompare:(NSNumber *)aNumber {
return [aNumber compare:self];
}
The good thing is that you can reuse everywhere and don't have to write the loop with reverse iterate. The bad thing is that you have to write more code:)
use sortarrayusingcomparator method like that
NSArray *sortedArray = [array sortedArrayUsingComparator:
^NSComparisonResult(id obj1, id obj2){
return [obj2 compare:obj1];
}];
by reversing the order of objects you will obtain a descending order
There are a few ways:
Write a comparison function and pass it to sortUsingFunction:context:.
Use sortUsingComparator:, which takes a block. (Only available in Mac OS X 10.6 and later and iOS 4.0 and later.)
Use sortUsingDescriptors:, and pass an array of at least one sort descriptor whose ascending property is false.
In the first two cases, your comparison should simply return the negation of what the comparator you normally use (e.g., compare:) returned. The last one involves less custom code, so it's what I'd use.
I have a mutableArray and want to sort in descending order with "number" key. "number" key is a string like "12345", "12346". This way that I had tried and look very well. Hope help you!
NSComparisonResult result;
NSArray *arrTem = [multableArr sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if([obj1 valueForKey:#"number"] > [obj2 valueForKey:#"number"])
result = NSOrderedDescending;
result = NSOrderedSame;
}];
return [[NSMutableArray alloc]initWithArray:arrTem];
For Example Data is Like this and we want to sort NSArray based on sId key.
<__NSArrayM 0x7ffc725af1d0>(
{
sId = 3;
vName = ABC;
},
{
sId = 10;
vName = DEF;
},
{
sId = 9;
vName = GHI;
},
{
sId = 7;
vName = JKL;
},
{
sId = 1;
vName = MNO;
}
)
Solution is as Below
NSArray *sortedArray = [arrOptions sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([[obj1 valueForKey:#"sId"] integerValue] > [[obj2 valueForKey:#"sId"] integerValue]) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([[obj1 valueForKey:#"sId"] integerValue] < [[obj2 valueForKey:#"sId"] integerValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
NSLog(#"Sorted Service Array is ::%#",sortedArray);
comare selector has to return NSComparisonResult. It's actually your function, so you can write another function, that returns the opposite result to sort in descending order.
The Dr. Touch website has a nice implementation of a category on NSArray to create a self-sorting array. This could be modified to keep the sort in whatever order was appropriate.
If you need based on ABCD in ascending then use following code
NSSortDescriptor *descriptor=[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors=[NSArray arrayWithObject: descriptor];
NSArray *reverseOrder=[yourArray sortedArrayUsingDescriptors:descriptors];
we can do it simply by using sortUsingSelector. The code as follows;
NSMutableArray *arr=[[NSMutableArray alloc]initWithObjects: ..objects.. ];
//Can also use NSArray.
[arr sortUsingSelector:#selector(compare:options:)];
NSString *temp;
int i,j;
i=0;
j=[arr count];
for(i=0;i<([arr count]-1);i++)
{
temp=[arr objectAtIndex:i];
[arr replaceObjectAtIndex:i withObject:[arr objectAtIndex:j]];
[arr replaceObjectAtIndex:j withObject:temp];
j--;
}
NSLog(#"New array is:%#",arr);
You may think that WHAT A STUPID ANSWER it is :D :D Actually, am not teasing anyone. But in simple logic, we can sort array in descending order by this way. No need of using any type of descriptors or any other complicated stuffs. And it will be easier for entry level programmers.
Use the following code to sort Array on the basis of key on which you want to sort tge array (e.g name , code, address,emp_id etc...)
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Enter Sort Type" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
return [array sortedArrayUsingDescriptors:sortDescriptors];

Sort an array with numeric strings

Hello I have an array of persons, and i am trying to sort them by age using a sort descriptor.
The age field in a patient is a string so when calling:
ageSorter = [[NSSortDescriptor alloc] initWithKey:#"age" ascending:YES];
[personList sortUsingDescriptors:[NSArray arrayWithObject:ageSorter]];
It sorts them but 100 appears first because its is not using numericSearch in the compare options.
Is there a ways i can still sort with descriptor but maybe using a selector to change how to compare the strings?
The finderSortWithLocale method (both these are taken from apple api):
int finderSortWithLocale(Person *person1, Person *person2, void *locale)
{
static NSStringCompareOptions comparisonOptions = NSNumericSearch;
NSRange string1Range = NSMakeRange(0, [string1 length]);
NSString *age1 = person1.age;
NSString *age2 = person2.age;
return [age1 compare:age2
options:comparisonOptions
range:string1Range
locale:(NSLocale *)locale];
}
How to call this method (edited: call the function on array of Persons):
NSArray *sortedArray = [personList sortedArrayUsingFunction:finderSortWithLocale
context:[NSLocale currentLocale]];
I also faced the same issue and found answer here.
Instead of NSString comparison, do with your object property. i.e for age.
Example. : In ascending order :
NSArray *sortedArray = [_arrayCaptureLeadList sortedArrayUsingComparator:^(Person *obj1, Person *obj2) {
return [obj1.age compare:obj2.age options:NSNumericSearch];
}];
NSMutableArray *filterResultArray = [NSMutableArray arrayWithArray:sortedArray];
In descending order :
NSArray *sortedArray = [_arrayCaptureLeadList sortedArrayUsingComparator:^(Person *obj1, Person *obj2) {
return [obj2.age compare:obj1.age options:NSNumericSearch];
}];
NSMutableArray *filterResultArray = [NSMutableArray arrayWithArray:sortedArray];
I know this is very late to reply your question but may this will be helpful for others. ^_^
You could create a category on NSString that adds a method numericCompare: and which calls [self compare:otherString options:NSNumericSearch]. Another option is to convert the age field into a NSNumber instead of a NSString. Yet another option involves a NSComparator block and sortUsingComparator.

How Do I sort an NSMutable Array with NSNumbers in it?

I'm trying to make a high score table, and suck at arrays in objective c (actually, in general objective c is challenging for me), so I can't figure out how to sort. I'm trying to do something like this (speudocode, I'm writing this in actionscript style because I'm more comfortable with it):
highscores.addObjecttoArray(score)
highscores.sort(ascending)
But I can't figure it out... I've seen other threads about it, but their use plist files and stuff and I don't know enough objective c to learn from them.
Would you like to do that the short way?
If you have a mutable array of NSNumber instances:
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO];
[mutableArrayOfNumbers sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];
Nice and easy :)
You can also perform similar sorting with descriptors on immutable arrays, but you will end up with a copy, instead of in-place sorting.
[highscores sortUsingSelector:#selector(compare:)];
Should work if they're definitely all NSNumbers.
(Adding an object is:
[highscores addObject:score];
)
If you want to sort descending (highest-first):
10.6/iOS 4:
[highscores sortUsingComparator:^(id obj1, id obj2) {
if (obj1 > obj2)
return NSOrderedAscending;
else if (obj1 < obj2)
return NSOrderedDescending;
return NSOrderedSame;
}];
Otherwise you can define a category method, e.g.:
#interface NSNumber (CustomSorting)
- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber;
#end
#implementation NSMutableArray (CustomSorting)
- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber {
return [otherNumber compare:self];
}
#end
And call it:
[highscores sortUsingSelector:#selector(reverseCompare:)];
I tried the answer provided by ohhorob, but the objects were still being sorted alphabetically. Then I ran across this in another answer (https://stackoverflow.com/a/4550451/823356):
I changed my NSSortDescriptor and it now sorts numerically.
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"score"
ascending:YES
comparator:^(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
I just thought I'd drop this in here as it solved my 'alphabetical sorting of NSNumbers' problem
For all it's worth, here is another shorthand method:
NSArray* n = #[#8, #3, #1, #12, #16, #7, #0, #5];
NSArray* asc = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
return [n1 compare:n2];
}];
NSLog(#"Ascending: %#", asc);
NSArray* dec = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
return [n2 compare:n1];
}];
NSLog(#"Descending: %#", dec);
This code will sort an NSMutableArray of NSNumber in ascending order:
[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
This code will sort an NSMutableArray of NSNumber in descending order:
[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2] * -1; // reverse the enum
}];
The code uses the fact that the NSNumber compare: method returns an NSComparisonResult that ranges from -1 to 1. Multiplying the result of the compare by -1 reverses the result and thereby reverses the sort to descending order.
distance is a key and it's value link (float or double)
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"distance"
ascending:YES
comparator:^(id obj1, id obj2)
{
return [obj1 compare:obj2 options:NSNumericSearch];
}];
NSArray *myArray = [NSArray arrayWithArray:arraySubCat];
myArray=[myArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor,nil]];
arraySubCat = [myArray copy];
For Descending Order:
NSArray *DescendingArray = [MinMaxArray sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"doubleValue"
ascending:NO]]];
For ascending Order
NSArray *AscendingArray = [MinMaxArray sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"doubleValue"
ascending:YES]]];

Sorting an array of doubles or CLLocationDistance values on the iPhone

I'm trying to sort a list of CLLocationDistance values by closest distance (ascending order). I first converted the values to NSString objects so that I could use the following sort:
NSArray *sortedArray;
sortedArray = [distances sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSString cannot sort on the numeric value.
How can I set a list of numeric values in ascending order?
I think what you want is sortedArrayUsingFunction:context: using something like this:
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
// sort things
NSArray *sortedArray; sortedArray = [anArray sortedArrayUsingFunction:intSort context:NULL];
apple docs reference
Try using sortedArrayUsingSelector where you define the function to compare the elements heres a reference :http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/sortedArrayUsingSelector:
When you convert the values to strings the sort will be lexicographical instead of numerical, which is not what you want according your question. CLLocationDistance is defined to be type double according to the Apple docs. Given that, create your NSArray with NSNumber instances initialized with your CLLocationDistance data (see numberWithDouble), and use NSArray's sorting implementation against those.
More on NSNumber is here.