iPhone OS:使用 NSPredicate Nsfetchrequest 和核心数据获取随机实体实例

发布于 2024-09-01 11:15:51 字数 271 浏览 13 评论 0原文

在开发一个应用程序时,我有大量的托管对象集合,我想针对这些对象获取一些随机实例。

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

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

另外,确定表“计数”的最佳方法是什么,以便我可以设置随机数生成器的范围。

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

谢谢!

缺口

Working on an app where I have a large collections of managed objects against which I want to fetch a few random instances.

My question is, is there any way I can use NSPredicate and NSFetchRequest to return several objects at random.

I saw that you could actually add a NSFetchRequest into the entity using the data modeler, any way to do the random fetch using this?

Also what would be the best method for determining the "count" of a table so I can set the bounds of the random number generator.

let me know if you need more details.

Thanks!

Nick

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

入画浅相思 2024-09-08 11:15:51

相反,将 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];

Instead use the fetchLimit in conjunction with the fetchOffset that way you can efficiently fetch only a single entity into memory:

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];
暮年慕年 2024-09-08 11:15:51

这可能不完全是您实现此操作的方式,但希望它能帮助您入门。

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

#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

如果您需要在不进行替换的情况下进行采样,以消除重复项,您可以创建一个 randomEntityIndexNSSet > NSNumber 对象,而不只是随机采样 int

在这种情况下,从有序的 NSSet 中进行采样,在将 NSNumber 对象从包中取出时将其删除,并减少 myEntityCount 以便从集合中随机选择一个 NSNumber 对象。

This may not be exactly how you implement this, but hopefully it will get you started.

Somewhere in your header or at the top of your implementation file:

#import <stdlib.h>
#import <time.h>

Elsewhere in your implementation:

//
// 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

If you need to sample without replacement, to eliminate duplicates, you might create an NSSet of randomEntityIndex NSNumber objects, instead of just sampling random ints.

In this case, sample from an ordered NSSet, remove NSNumber objects as you pull them out of the bag, and decrement myEntityCount for the purposes of picking a random NSNumber object from the set.

我很OK 2024-09-08 11:15:51

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

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

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

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

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

I've searched around a lot for this, essentially Coredata won't give you any random rows, and it is not meant to. You have to create your own.

This is what I came up with up with, assuming we are using an NSPredicate and theres no primary Unique key, this is the best possible answer i think with the least overhead.

  1. Set NSFetchRequest type to NSManagedObjectID. Turn everything off, to minimize overhead.
  2. Execute fetch request with your desired predicate, Do Not use any FetchLimit.
  3. From the received NSManagedObjectID array. get your random number of objects. this is a good solution: Get n random objects (for example 4) from nsarray

  4. Now you've got random NSManagedObjectIDs of your desired count, (which are more or less random)

  5. Loop through the random objectID array and Use NSManagedObjectContext objectWithID: to get the objects.
梦里人 2024-09-08 11:15:51

这就是我根据 Corey Floyd 的答案在 Swift 中所做的,给定一个 Verb 实体。
一些手动测试给了我令人满意的随机结果。

let request = Verb.fetchRequest()

do {
    let count = try self.context.count(for: request)
            
    let randomOffset = Int.random(in: 0..<count)
    request.fetchOffset = randomOffset
    request.fetchLimit = 1
            
    let verbs = try self.context.fetch(request)
}
catch let error {
    print(error.localizedDescription)
}

This is what I did in Swift based on Corey Floyd's answer, given a Verb entity.
A few manual tests give me satisfactory random results.

let request = Verb.fetchRequest()

do {
    let count = try self.context.count(for: request)
            
    let randomOffset = Int.random(in: 0..<count)
    request.fetchOffset = randomOffset
    request.fetchLimit = 1
            
    let verbs = try self.context.fetch(request)
}
catch let error {
    print(error.localizedDescription)
}
忆梦 2024-09-08 11:15:51

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

myEntityCount = [myEntities count]

If you are fetching all the objects anyway, there is no need for the first request to get the object count. You can just use something like:

myEntityCount = [myEntities count]
汐鸠 2024-09-08 11:15:51

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

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

Solution suggested by Core will not work if you need to randomize the fetch within a subset table rows restricted by a predicate (e.g. "where something < something").

The best solution I have so far (where I do not need to fetching all or large number of rows) is using randomly selecting based on a primary key (off course the requires a primary key in the table, preferably w/o any missing values).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文