11

在我有大量托管对象的应用程序上工作,我想从中获取一些随机实例。

我的问题是,有什么方法可以使用 NSPredicate 和 NSFetchRequest 随机返回多个对象。

我看到您实际上可以使用数据建模器将 NSFetchRequest 添加到实体中,有什么方法可以使用它进行随机提取?

还有什么是确定表格“计数”的最佳方法,这样我就可以设置随机数生成器的界限。

如果您需要更多详细信息,请告诉我。

谢谢!

缺口

4

5 回答 5

20

而是将 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];
于 2011-03-06T04:09:50.260 回答
5

这可能不是你实现它的确切方式,但希望它能让你开始。

在您的标题或实现文件顶部的某个位置:

#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

如果您需要在不替换的情况下进行采样,以消除重复项,您可以创建一个NSSetofrandomEntityIndex NSNumber对象,而不是仅仅采样 random ints。

在这种情况下,从一个有序的 中取样,从袋子NSSet中取出NSNumber对象,然后递减以从集合中myEntityCount随机挑选一个对象。NSNumber

于 2010-05-13T22:17:08.740 回答
2

我已经为此搜索了很多,基本上Coredata不会给你任何随机行,它不是故意的。你必须创建你自己的。

这就是我想出的,假设我们使用的是一个NSPredicate并且没有主唯一键,这是我认为开销最小的最佳答案。

  1. NSFetchRequest类型设置为NSManagedObjectID。关闭一切,以尽量减少开销。
  2. 使用您想要的谓词执行获取请求, 不要使用任何 FetchLimit
  3. 从接收到的NSManagedObjectID数组。获取随机数量的对象。这是一个很好的解决方案:从 nsarray 获取 n 个随机对象(例如 4 个)

  4. 现在你已经得到NSManagedObjectIDs了你想要的随机数,(或多或少是随机的)

  5. 循环遍历随机 objectID 数组并使用NSManagedObjectContext objectWithID:来获取对象。
于 2015-02-23T22:01:04.167 回答
0

如果无论如何您要获取所有对象,则不需要第一个请求来获取对象计数。你可以使用类似的东西:

myEntityCount = [myEntities count]
于 2010-12-14T00:18:51.333 回答
0

如果您需要在受谓词限制的子表行中随机化获取(例如“其中某物 < 某物”),Core 建议的解决方案将不起作用。

到目前为止我最好的解决方案(我不需要获取所有或大量行)是使用基于主键的随机选择(当然需要表中的主键,最好没有任何缺失值)。

于 2013-04-29T20:28:46.240 回答