我有一个核心数据应用程序。我想要获取一种对象User
。 User
拥有属性userId
。
我有另一个数组userId
s,[1, 4, 3, 5]
。我想创建一个NSSortDescriptor
,根据数组中User
的顺序对userId
个对象进行排序。
这可能吗,我应该怎么做?
更新
我现在尝试了以下内容。
我在User对象中添加了一个可转换的属性,在那里我存储了用户id数组。
我尝试了以下排序描述符:
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
。任何想法应该如何看待这种关系?见附图。那是对的吗?
答案 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
,我用它来排序消息IDNSSortDescriptor *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];