Jorge
Jorge

Reputation: 1532

Sort NSArray based on another NSArray using sortDescriptors

I have an NSArraywith stringsobjects that don't follow a pattern, like:

D C A Z X.

When I try to sort a similar array by ascending order, I get:

A C D X Z.

That's not the result I want, I need to achieve the same pattern as the reference array. I'm just not sure how to do this using NScomparisonResultor NSSortDescriptor.

The second array, may not be exactly the same, but I need to have the same order. for example, maybe I have D X A. Based on the reference array I need to get D A X.

UPDATE:

Ok, so here is my code:

- (PFQuery *)queryForTable {
    PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];

     // This is the reference array
     NSArray *labels = [@"Café da Manhã", @"Meio da Manhã", @"Almoço", @"Meio da Tarde", @"Final da Tarde", @"Jantar", @"Pós-Treino"];

    NSSortDescriptor *descriptor = 
    [NSSortDescriptor sortDescriptorWithKey:@"refeicao" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        NSUInteger index1 = [labels indexOfObject:obj1];
        NSUInteger index2 = [labels indexOfObject:obj2];
        return index1 - index2;
    }];

    [query orderBySortDescriptor:descriptor];
    return query;
}

I have an array of PFObjects, which I need to order by the key refeicao.

Upvotes: 1

Views: 767

Answers (2)

Clay Bridges
Clay Bridges

Reputation: 11880

This is kind-of an answer to your original, more general question. It may not be optimally efficient, but looks O(N)-ish. I suspect it's faster than comparators. This assumes that jumbledArray is a subset of referenceArray; you could get around that if needed.

NSArray *referenceArray = @[@"S", @"E", @"T", @"Z", @"R", @"U", @"L"];
NSArray *jumbledArray = @[@"R", @"E", @"S", @"T"];

NSMutableOrderedSet *setToOrder = [[NSMutableOrderedSet alloc] initWithArray:jumbledArray];

NSUInteger insertIndex = 0;

for (NSString *refString in referenceArray) {
    NSUInteger presentIndex = [setToOrder indexOfObject:refString]; // one lookup, presumably cheap

    if (presentIndex != NSNotFound) {
        [setToOrder moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:presentIndex] toIndex:insertIndex];
        insertIndex++;
    }
}
// [setToOrder array] == @[@"S", @"E", @"T", @"R"]

You could generalize this as a method, something like:

- (NSArray *)arrayBySortingArray:(NSArray *)jumbledArray usingReferenceArray:(NSArray *)referenceArray

Upvotes: 2

Wain
Wain

Reputation: 119031

You will need to write your own comparison method (which can tie in with a sort descriptor as you can implement it as an NSComparator).

This method will need to find the 2 strings being compared in your reference array and use the index positions for the comparison. The actual values will not be compared, everything is about the position of the corresponding strings in the reference array.

Upvotes: 3

Related Questions