2

I have an NSArray of NSDictionaries. In the NSDictionary I have an element called 'rowID' which is saved as an NSString. However, everything saved in it is a number even though they saved as a string.

I would like to know how to sort the array based on this value but in terms of sorting 1-100. Currently, when I sort it 10 comes first when it should be 1-10.

This is how I am sorting:

NSArray *tempSortedItemsArray = [itemArray sortedArrayUsingDescriptors:
                                     @[[NSSortDescriptor
                                        sortDescriptorWithKey:@"rowID" ascending:YES]]];
Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
HurkNburkS
  • 5,492
  • 19
  • 100
  • 183

4 Answers4

7

Try this :-

NSArray *aSortedArray = [itemArray sortedArrayUsingComparator:^(NSMutableDictionary *obj1,NSMutableDictionary *obj2) {
    NSString *num1 =[obj1 objectForKey:@"rowID"];
    NSString *num2 =[obj2 objectForKey:@"rowID"];
    return (NSComparisonResult) [num1 compare:num2 options:(NSNumericSearch)];
}];
Leena
  • 2,678
  • 1
  • 30
  • 43
  • This is incorrect. The OP has stated that the rowIDs are `NSString` objects, not `NSNumber` objects. This will end up doing the same incorrect string comparison. – rmaddy Feb 15 '14 at 06:00
  • it worked fine at my end test it if you find incorrect result then i will delete my answer – Leena Feb 15 '14 at 06:03
  • It's correct if the `rowID` values are actually `NSNumber` objects but the OP has `NSString` objects. – rmaddy Feb 15 '14 at 06:06
  • this worked for me... the values are NSStrings... why is it working for me? – HurkNburkS Feb 15 '14 at 06:48
  • because of Numeric Search thats what you wanted.. – Leena Feb 15 '14 at 06:54
2

You can get numeric sorting by following this code:-

NSMutableArray *tmpAr = [[NSMutableArray alloc] init];

NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number5"];
[tmpDict setObject:@"5" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number3"];
[tmpDict setObject:@"3" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number2"];
[tmpDict setObject:@"2" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number1"];
[tmpDict setObject:@"1" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number4"];
[tmpDict setObject:@"4" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number25"];
[tmpDict setObject:@"25" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number10"];
[tmpDict setObject:@"10" forKey:@"id"];
[tmpAr addObject:tmpDict];

tmpDict = [[NSMutableDictionary alloc] init];
[tmpDict setObject:@"name" forKey:@"number7"];
[tmpDict setObject:@"7" forKey:@"id"];
[tmpAr addObject:tmpDict];

NSLog(@"tmpar1 = %@",tmpAr);

[tmpAr sortUsingComparator:
 ^(id obj1, id obj2)
 {
     NSInteger value1 = [[obj1 objectForKey: @"id"] intValue];
     NSInteger value2 = [[obj2 objectForKey: @"id"] intValue];
     if (value1 > value2)
     {
         return (NSComparisonResult)NSOrderedDescending;
     }

     if (value1 < value2)
     {
         return (NSComparisonResult)NSOrderedAscending;
     }
     return (NSComparisonResult)NSOrderedSame;
 }];

NSLog(@"tmpar2 = %@",tmpAr);
Sunil Zalavadiya
  • 1,993
  • 25
  • 36
1

If you create your sort descriptor with initWithKey:ascending:selector: or sortDescriptorWithKey:ascending:comparator: you can specify a selector used to compare objects.

Now the problem is which selector to pass. Well, you can create a Category on NSString implementing a custom sort function that sorts based on the numeric value of the string. Remember that from the documents:

The selector must specify a method implemented by the value of the property identified by keyPath. The selector used for the comparison is passed a single parameter, the object to compare against self, and must return the appropriate NSComparisonResult constant. The selector must have the same method signature as:

- (NSComparisonResult)localizedCompare:(NSString *)aString

The object at the specified property key, relative to each object in the collection, must implement the compare selector used to create the sort descriptor. If no custom selector was specified, the objects must implement compare.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
Merlevede
  • 8,140
  • 1
  • 24
  • 39
1

Try like this :-

NSDictionary *row1 = [NSDictionary dictionaryWithObjectsAndKeys:@"1",@"rowId",nil];
NSDictionary *row2 = [NSDictionary dictionaryWithObjectsAndKeys:@"2",@"rowId",nil];
NSDictionary *row3 = [NSDictionary dictionaryWithObjectsAndKeys:@"3",@"rowId",nil];

NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:row1,row2,row3,nil];

NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:@"rowId" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:desc]];

// before sort
NSLog(@"Before %@",arr);
[arr sortedArrayUsingComparator:^(NSDictionary *item1, NSDictionary *item2) {
    NSString *first = [item1 objectForKey:@"rowId"];
    NSString *second = [item2 objectForKey:@"rowId"];
    return [first compare:second options:NSNumericSearch];
}];
// After sort
NSLog(@"After %@",arr);
Hussain Shabbir
  • 14,801
  • 5
  • 40
  • 56