NSSortDescriptor - 基于另一个数组对描述符进行排序

时间:2013-05-13 07:59:33

标签: ios objective-c cocoa-touch core-data nssortdescriptor

我有一个核心数据应用程序。我想要获取一种对象UserUser拥有属性userId

我有另一个数组userId s,[1, 4, 3, 5]。我想创建一个NSSortDescriptor,根据数组中User的顺序对userId个对象进行排序。

这可能吗,我应该怎么做?

更新

我现在尝试了以下内容。

  1. 我在User对象中添加了一个可转换的属性,在那里我存储了用户id数组。

  2. 我尝试了以下排序描述符:

    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"userId" ascending:YES     comparator:^NSComparisonResult(id obj1, id obj2) {
        NSUInteger idx1 = [self.user.followingIds indexOfObject:[obj1 valueForKey:@"userId"]];
        NSUInteger idx2 = [self.user.followingIds indexOfObject:[obj2 valueForKey:@"userId"]];
        return idx1 - idx2;
    }];
    
  3. 我收到以下错误:

    Serious application error.  Exception was caught during Core Data change processing.  This  is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.   [<__NSCFNumber 0xa337400> valueForUndefinedKey:]: this class is not key value coding-compliant  for the key userId. with userInfo {
        NSTargetObjectUserInfoKey = 2502;
        NSUnknownUserInfoKey = userId;
    }
    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:    '[<__NSCFNumber 0xa337400> valueForUndefinedKey:]: this class is not key value coding-   compliant for the key userId.'
    

    更新2

    还要在Followers个对象之间添加关系User。任何想法应该如何看待这种关系?见附图。那是对的吗?

    enter image description here

3 个答案:

答案 0 :(得分:5)

使用排序描述符无法做到这一点,您必须在获取结果后应用自定义比较器函数:

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;
}];

答案 1 :(得分:2)

正如@MartinR所说,你不能用排序描述符来做到这一点 为了实现O(N)复杂度的可扩展解决方案(如果你真的需要它):

//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;
    }
}

分析:(如果发现任何错误,请纠正我)

映射阶段完成N次操作:O(N)
阵列复制需要N次操作:O(N)
循环迭代N次,但是:
     它在最多N次交换时执行
  并且在最大N比较中 因此:O(N)+ O(N)+ O(N)+ O(N)= 4 * O(N)= O(N)

@MartinR解决方案将基于基于比较的排序,限制为最小O(N * lg(N))操作。
但是每次比较都需要O(N)来获得第一个索引,O(N)获得第二个索引 因此:O(N * lg(N))*(O(N)+ O(N))= 2 * O(N)* O(N * lg(N))= O((N ^ 2)* lg (N))

对于足够小的N,没有真正的区别(对于我的解决方案,N = 10 ==&gt; ~40次操作,对于Martin的解决方案,约为200次操作)。
对于大N马丁的解决方案将无法很好地扩展:
N == 1000 ==&gt;我的解决方案~4000次操作和~2 * 1000 * 1000 * 8 = ~16 * 10 ^ 6

答案 2 :(得分:1)

使用这个想法,如果它被添加到DB

,我用它来排序消息ID
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];