1

I am trying to sort a large range of products by price first then by title, then display them:

Applying both sorting doesn't seems to work, HOWEVER, applying one sort of them works fine, so if I apply sorting by price, it will return products sorted by price, the same thing for title. So why I am not able to sort by both price and title?

//Sort by Price, then by Title. Both Ascending orders
arrayProduct = (NSMutableArray*)[arrayProduct sortedArrayUsingFunction:priceComparator context:nil];
arrayProduct = (NSMutableArray*)[arrayProduct sortedArrayUsingFunction:titleComparator context:nil];


//products comparators
NSInteger priceComparator(NSMutableDictionary *obj1, NSMutableDictionary *obj2, void *context){


    int v1 = [[[obj1 valueForKey:@"Product Sale Price"]substringFromIndex:1] intValue];
    int v2 = [[[obj2 valueForKey:@"Product Sale Price"]substringFromIndex:1] intValue];

    if (v1 < v2){

        return NSOrderedAscending;
    }
    else if (v1 > v2){

        return NSOrderedDescending;

    }
    else
        return NSOrderedSame;

}

NSInteger titleComparator(NSMutableDictionary *obj1, NSMutableDictionary *obj2, void *context){

    NSString* v1 = [obj1 valueForKey:@"Product Title"];
    NSString* v2 = [obj2 valueForKey:@"Product Title"];

    if ([v1 caseInsensitiveCompare:v2] == NSOrderedAscending){

        return NSOrderedAscending;
    }
    else if ([v1 caseInsensitiveCompare:v2] == NSOrderedDescending){

        return NSOrderedDescending;
    }
    else
        return NSOrderedSame;

}
pattivacek
  • 5,617
  • 5
  • 48
  • 62
Malloc
  • 15,434
  • 34
  • 105
  • 192
  • I don't believe that `sortedArrayUsingFunction:context:` guarantees to preserve any "secondary" ordering of the elements. From the docs: "Returns a new array that lists the receiving array’s elements in ascending order as defined by the comparison function comparator." – Nicholas Hart Aug 14 '13 at 16:31
  • So, what would be a better way to sort the array by two parameters (price then title) ? – Malloc Aug 14 '13 at 16:38
  • Try something like this: http://stackoverflow.com/questions/10142974/sorting-arrays-in-objective-c – Nicholas Hart Aug 14 '13 at 16:54

2 Answers2

9

You are getting incorrect results because you're sorting the entire array twice. Here are some other options:

You could use blocks

[arrayProduct sortUsingComparator:^NSComparisonResult(id a, id b) {
    NSMutableDictionary * dictA = (NSMutableDictionary*)a;
    NSMutableDictionary * dictB = (NSMutableDictionary*)b;

    NSInteger p1 = [[[dictA valueForKey:@"Product Sale Price"]substringFromIndex:1] integerValue];
    NSInteger p2 = [[[dictB valueForKey:@"Product Sale Price"]substringFromIndex:1] integerValue];

    if(p1 > p2){
        return NSOrderedAscending;
    }
    else if(p2 > p1){
        return NSOrderedDescending;
    }
    //Break ties with product titles
    NSString* v1 = [dictA valueForKey:@"Product Title"];
    NSString* v2 = [dictB valueForKey:@"Product Title"];

    return [v1 caseInsensitiveCompare:v2];
}];

Or NSSortDescriptors ( http://developer.apple.com/library/ios/documentation/cocoa/Conceptual/SortDescriptors/Articles/Creating.html )

ikaver
  • 701
  • 1
  • 5
  • 6
  • Hi iKaver, have you test the sample above? it doesn't sort correctly – Malloc Aug 14 '13 at 17:20
  • Hi Malloc, I forgot to mention in the example that the arrayProduct array is not being sorted, its returning a sorted array. I'll edit the code to clarify. – ikaver Aug 14 '13 at 17:24
  • I modified it so the array itself gets sorted. Let me know if that solves your problem :) – ikaver Aug 14 '13 at 17:30
1

I think the problem here is that you are sorting once by price and then resorting the entire array by title, overwriting any sorting done by the first round. It seems that what you want is an array sorted by price, and if the price for two or more items is the same, that subset will be sorted by title. To do that, you should only sort once and thus only have one Comparator function. You essentially need to combine the two you have. First use the logic for the prices, but if v1 == v2 then use the logic for titles.

pattivacek
  • 5,617
  • 5
  • 48
  • 62
  • Hi, I already got this, and tried to combine both sorting exactly as you said. But it didn't returned me the wanted results – Malloc Aug 14 '13 at 16:37