在我有大量托管对象的应用程序上工作,我想从中获取一些随机实例。
我的问题是,有什么方法可以使用 NSPredicate 和 NSFetchRequest 随机返回多个对象。
我看到您实际上可以使用数据建模器将 NSFetchRequest 添加到实体中,有什么方法可以使用它进行随机提取?
还有什么是确定表格“计数”的最佳方法,这样我就可以设置随机数生成器的界限。
如果您需要更多详细信息,请告诉我。
谢谢!
缺口
在我有大量托管对象的应用程序上工作,我想从中获取一些随机实例。
我的问题是,有什么方法可以使用 NSPredicate 和 NSFetchRequest 随机返回多个对象。
我看到您实际上可以使用数据建模器将 NSFetchRequest 添加到实体中,有什么方法可以使用它进行随机提取?
还有什么是确定表格“计数”的最佳方法,这样我就可以设置随机数生成器的界限。
如果您需要更多详细信息,请告诉我。
谢谢!
缺口
而是将 fetchLimit 与 fetchOffset 结合使用,这样您就可以有效地将单个实体提取到内存中:
NSFetchRequest *myRequest = [[NSFetchRequest alloc] init];
[myRequest setEntity: [NSEntityDescription entityForName:myEntityName inManagedObjectContext:myManagedObjectContext]];
NSError *error = nil;
NSUInteger myEntityCount = [myManagedObjectContext countForFetchRequest:myRequest error:&error];
NSUInteger offset = myEntityCount - (arc4random() % myEntityCount);
[myRequest setFetchOffset:offset];
[myRequest setFetchLimit:1];
NSArray* objects = [myManagedObjectContext executeFetchRequest:myRequest error:&error];
id randomObject = [objects objectAtIndex:0];
这可能不是你实现它的确切方式,但希望它能让你开始。
在您的标题或实现文件顶部的某个位置:
#import <stdlib.h>
#import <time.h>
在您的实施中的其他地方:
//
// get count of entities
//
NSFetchRequest *myRequest = [[NSFetchRequest alloc] init];
[myRequest setEntity: [NSEntityDescription entityForName:myEntityName inManagedObjectContext:myManagedObjectContext]];
NSError *error = nil;
NSUInteger myEntityCount = [myManagedObjectContext countForFetchRequest:myRequest error:&error];
[myRequest release];
//
// add another fetch request that fetches all entities for myEntityName -- you fill in the details
// if you don't trigger faults or access properties this should not be too expensive
//
NSArray *myEntities = [...];
//
// sample with replacement, i.e. you may get duplicates
//
srandom(time(NULL)); // seed random number generator, so that you get a reasonably different series of random integers on each execution
NSUInteger numberOfRandomSamples = ...;
NSMutableSet *sampledEntities = [NSMutableSet setWithCapacity:numberOfRandomSamples];
for (NSInteger sampleIndex = 0; sampleIndex < numberOfRandomSamples; sampleIndex++) {
int randomEntityIndex = random() % myEntityCount; // generates random integer between 0 and myEntityCount-1
[sampledEntities addObject:[myEntities objectAtIndex:randomEntityIndex]];
}
// do stuff with sampledEntities set
如果您需要在不替换的情况下进行采样,以消除重复项,您可以创建一个NSSet
ofrandomEntityIndex
NSNumber
对象,而不是仅仅采样 random int
s。
在这种情况下,从一个有序的 中取样,从袋子NSSet
中取出NSNumber
对象,然后递减以从集合中myEntityCount
随机挑选一个对象。NSNumber
我已经为此搜索了很多,基本上Coredata不会给你任何随机行,它不是故意的。你必须创建你自己的。
这就是我想出的,假设我们使用的是一个NSPredicate
并且没有主唯一键,这是我认为开销最小的最佳答案。
NSFetchRequest
类型设置为NSManagedObjectID
。关闭一切,以尽量减少开销。从接收到的NSManagedObjectID
数组。获取随机数量的对象。这是一个很好的解决方案:从 nsarray 获取 n 个随机对象(例如 4 个)
现在你已经得到NSManagedObjectIDs
了你想要的随机数,(或多或少是随机的)
NSManagedObjectContext objectWithID:
来获取对象。如果无论如何您要获取所有对象,则不需要第一个请求来获取对象计数。你可以使用类似的东西:
myEntityCount = [myEntities count]
如果您需要在受谓词限制的子表行中随机化获取(例如“其中某物 < 某物”),Core 建议的解决方案将不起作用。
到目前为止我最好的解决方案(我不需要获取所有或大量行)是使用基于主键的随机选择(当然需要表中的主键,最好没有任何缺失值)。