NSSortDescriptor - Sort descriptor based on another array

前端 未结 3 842
独厮守ぢ
独厮守ぢ 2021-01-13 05:39

I hava a core data application. And I want to fetch one kind of object, User. User have the property userId.

I have another a

相关标签:
3条回答
  • 2021-01-13 06:02

    As @MartinR said, you cannot do that with sort descriptors.
    To achieve a scalable solution in O(N) complexity (if you really need it):

    //Not tested
    NSArray* permutation = ...;//@[@1,@4,@3,@5] (user ids);
    NSMutableDictionary* map = [[NSMutableDictionary alloc] initWithCapacity:[permutation count]];
    for (NSUInteger i =0; i< [permutation count]; ++i) {
        map[permutation[i]] = @(i);
    }
    NSMutableArray* results = ...;//A mutable copy of the results
    for (NSUInteger i = 0; i < [permutation count];) {
        id userId = [results[i] valueForKey:@"userId"];
        NSUInteger key = [map[userId] unsignedIntegerValue];//where we like this object to be
        if (key != i) {
            [results exchangeObjectAtIndex:i withObjectAtIndex:key];
        } else {
            ++i;
        }
    }
    

    Analysis: (Please correct me if you spot any mistakes)

    The mapping stage takes N operation to complete: O(N)
    The array copy takes N operations: O(N)
    The loop iterate N times, but:
    it perform at max N exchanges
    and at max N comparisons
    hence: O(N) + O(N) + O(N) + O(N) = 4*O(N) = O(N)

    @MartinR solution will be based on a comparison based sort limited to a minimum O(N*lg(N)) operations.
    however each comparison takes O(N) to get the first index and O(N) to get the second index.
    hence: O(N*lg(N))*(O(N) + O(N)) = 2*O(N)*O(N*lg(N)) = O((N^2)*lg(N))

    For small enough N there is no real difference (N=10 ==> ~40 operations for my solution and ~200 operations for Martin's solution).
    For large N Martin's solutions will not scale well:
    N == 1000 ==> ~4000 operations for my solution and ~2*1000*1000*8 =~ 16*10^6

    0 讨论(0)
  • 2021-01-13 06:12

    Use this idea which i use to sort message id if it is added to DB

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"message_id" ascending:NO selector:@selector(localizedStandardCompare:)];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
        [request setSortDescriptors:sortDescriptors];
        request.returnsObjectsAsFaults=NO;
     NSError *error = nil;
        NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
    
    0 讨论(0)
  • 2021-01-13 06:14

    This can not be done with a sort descriptor, you have to apply a custom comparator function after fetching the results:

    NSArray *userIds = ...; // e.g. @[@1, @4, @3, @5]
    NSArray *results = ...; // result of fetch request
    NSArray *sorted = [results sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSUInteger idx1 = [userIds indexOfObject:[obj1 valueForKey:@"userId"]];
        NSUInteger idx2 = [userIds indexOfObject:[obj2 valueForKey:@"userId"]];
        return idx1 - idx2;
    }];
    
    0 讨论(0)
提交回复
热议问题