Reputation: 7410
I have a simple NSArray
, containing NSNumber
s.
I sort the array in an ascending order this way :
NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
[_scores sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];
My problem is, I'd like the NSNumber
s containing 0
to be at the end rather than at the beginning. Here is the kind of array I may have to sort (containing some empty NSNumber
s just for the example):
0
25
12
0
8
0
My code of course sorts the array like this:
0
0
0
8
12
25
What I would like is this:
8
12
25
0
0
0
Of course I could re-order it manually by removing the lines with 0
and adding them at the end, but I'm looking for the cleanest solution possible.
Upvotes: 0
Views: 7006
Reputation: 86651
Sort the array using a comparator.
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
if ([obj1 integerValue] == 0 && [obj2 integerValue] == 0)
{
return (NSComparisonResult)NSOrderedSame;
}
if ([obj1 integerValue] == 0)
{
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj2 integerValue] == 0)
{
return (NSComparisonResult)NSOrderedAscending;
}
if ([obj1 integerValue] > [obj2 integerValue])
{
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 integerValue] < [obj2 integerValue])
{
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
Upvotes: 13
Reputation: 18253
@JeremyP's answer provides proper sorting, and is probably what you are after.
However, for completeness a way to do it with filters and the standard compare:
method:
NSArray *numbers = @[@12, @0, @10, @15, @0, @3];
NSArray *sortedPositiveNumbers = [[numbers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self > 0"]] sortedArrayUsingSelector:@selector(compare:)];
NSArray *zeroes = [numbers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self = 0"]];
NSArray *result = [sortedPositiveNumbers arrayByAddingObjectsFromArray:zeroes];
Thanks to Caleb for the spark.
Upvotes: 1
Reputation: 288
You can use NSPredicate
to filter the values you do not want..
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self > 0"];
NSMutableArray *filteredArray = [[_scores filteredArrayUsingPredicate:predicate] mutableCopy];
NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
[filteredArray sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];
Upvotes: 0
Reputation: 9040
This will solve your problem,
NSArray *sortedScores = [_scores sortedArrayUsiHelperComparator:^(id obj1, id obj2){
if([obj1 integerValue]==0 && [obj2 integerValue]==0){
return (NSComparisonResult) NSOrderedSame;
}else if([obj1 integerValue]==0){
return (NSComparisonResult) NSOrderedDescending;
}else if([obj2 integerValue]==0){
return (NSComparisonResult) NSOrderedAscending;
}
if([obj1 integerValue] >[obj2 integerValue]) return (NSComparisonResult) NSOrderedDescending;
if([obj1 integerValue] <[obj2 integerValue]) return (NSComparisonResult) NSOrderedAscending;
return (NSComparisonResult) NSOrderedSame;
}];
Upvotes: 4
Reputation: 124997
Method 1:
Step 1: sort the array.
Step 2: move the zeroes to the end of the array.
Method 2:
Step 1: write a comparator function that orders 0
after any other value.
Step 2: sort the array.
Upvotes: 1