【问题标题】:iPhone OS: Fetching a random entity instance using NSPredicate Nsfetchrequest and core dataiPhone OS:使用 NSPredicate Nsfetchrequest 和核心数据获取随机实体实例
【发布时间】:2011-02-19 07:22:06
【问题描述】:

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

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

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

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

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

谢谢!

尼克

【问题讨论】:

  • 额外信息:我想要获取的是具有两个属性的对象,一个 nsstring 长度为 1-50 个字符,以及一个伪主键 int 我认为可能有助于随机选择少量。我可以重新构建模型,但如有必要,我仍然可以制作这个吸盘的原型。
  • 此评论应添加到您的问题中。

标签: iphone core-data nspredicate nsfetchrequest


【解决方案1】:

而是将 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];

【讨论】:

  • 我尝试了这种获取随机对象的方法,因为我认为与不断重新获取超过 5k 条目的整个列表以提取一个随机对象相比,它的开销要少得多。然而,我发现无论偏移量是多少,我总是会收到相同的十个左右的托管对象之一。这种生成随机对象的方法绝不是“随机的”,因此,就我的使用而言,是不可接受的。遵循公认答案的开销很小,至少比我想象的要少得多。因此,我会推荐接受的答案而不是这个。
  • 我也遇到了麻烦......我需要从我的核心数据实例中获取一个随机项目并创建一个与 Corey Floyd 说的几乎相同的方法,但似乎有一些东西CoreData 不喜欢它并且它没有返回预期的结果......
  • +1 对于这个答案,但它需要一个小修复,当计算的偏移量等于 myEntityCount 时,提取将返回零记录,至少在我的情况下,所以我从计算的偏移量中减去 1。然后你需要另一个小检查 -> 如果 myEntityCount 为零,你实际上无法得到任何结果,那么你需要在计算偏移量之前退出该方法。
【解决方案2】:

这可能不是您实现它的确切方式,但希望它能帮助您入门。

在您的标题中或实现文件的顶部:

#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

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

在这种情况下,从已排序的 NSSet 中取样,将 NSNumber 对象从袋中拉出时将其移除,然后将 myEntityCount 递减以从集合中随机选择 NSNumber 对象。

【讨论】:

  • 嗨,Alex 非常感谢,非常酷!这看起来应该可以完美运行。我唯一担心的是 myEntities 数组将包含 3k-5k 个实例,即使有这么多数据,您是否认为它不会变得太慢?理想情况下,我希望在不抓取每个实体实例的情况下执行随机选择,我在这里找错树了吗?再次感谢亚历克斯!
  • 额外信息:我想要获取的是具有两个属性的对象,一个 nsstring 长度为 1-50 个字符,以及一个伪主键 int 我认为可能有助于随机选择少量。我可以重新构建模型,但如有必要,我仍然可以制作这个吸盘的原型。
  • 你绝对可以使用伪主键属性而不是抓取所有记录。
  • 酷,我会报告一下我最终做了什么,我正在阅读这本核心数据手册,并尽量避免睁大眼睛。很酷。
  • Core Data 返回的对象将是空的,除了它们的-objectID 属性,因此响应会非常快。只有您正在访问属性的对象才会被完全实现并拉入内存。
【解决方案3】:

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

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

  1. NSFetchRequest 类型设置为NSManagedObjectID。关闭一切,以尽量减少开销。
  2. 使用所需的谓词执行提取请求,不要使用任何 FetchLimit
  3. 来自收到的NSManagedObjectID 数组。获取随机数量的对象。这是一个很好的解决方案:Get n random objects (for example 4) from nsarray

  4. 现在您已经获得了所需数量的随机 NSManagedObjectIDs,(或多或少是随机的)

  5. 循环遍历随机objectID数组并使用NSManagedObjectContext objectWithID:获取对象。

【讨论】:

    【解决方案4】:

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

    myEntityCount = [myEntities count]
    

    【讨论】:

      【解决方案5】:

      如果您需要在受谓词限制的子表行中随机化提取(例如“where something

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

      【讨论】:

        猜你喜欢
        • 2015-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多