5

我有一个核心数据应用程序。我想获取一种对象,User. User有财产userId

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

这可能吗,我该怎么做?

更新

我现在尝试了以下方法。

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

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

我收到以下错误:

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任何想法应该如何看待这种关系?见附图。那是对的吗?

在此处输入图像描述

4

3 回答 3

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;
}];
于 2013-05-13T08:21:13.680 回答
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 ==> ~40 次操作,对于 Martin 的解决方案 ~200 次操作)。
对于大 N Martin 的解决方案无法很好地扩展:
我的解决方案的 N == 1000 ==> ~4000 次操作和 ~2*1000*1000*8 =~ 16*10^6

于 2013-05-13T09:21:09.363 回答
1

如果将消息ID添加到数据库中,请使用我用来对消息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];
于 2013-05-13T08:19:05.337 回答