IPhone OS: выборка случайного экземпляра объекта с использованием NSPredicate Nsfetchrequest и основных данных
Работа с приложением, где у меня есть большие коллекции управляемых объектов, против которых я хочу получить несколько случайных экземпляров.
Мой вопрос: есть ли способ использовать NSPredicate и NSFetchRequest для возврата нескольких объектов в случайном порядке.
Я видел, что вы действительно можете добавить NSFetchRequest в объект, используя модель данных данных, любым способом сделать случайную выборку с помощью этого?
Также будет лучшим методом определения "подсчета" таблицы, чтобы я мог установить границы генератора случайных чисел.
сообщите мне, если вам нужна дополнительная информация.
Спасибо!
Ник
Ответы
Ответ 1
Возможно, это не так, как вы это реализуете, но, надеюсь, вам это поможет.
Где-то в вашем заголовке или в верхней части вашего файла реализации:
#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
из randomEntityIndex
NSNumber
, а не просто выборку случайных int
s.
В этом случае образец из упорядоченного NSSet
, удалите объекты NSNumber
, вытаскивая их из сумки и уменьшая myEntityCount
для выбора случайного объекта NSNumber
из набора.
Ответ 2
Вместо этого используйте 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];
Ответ 3
Я много искал для этого, по сути, Coredata не даст вам случайных строк, и это не значит. Вы должны создать свой собственный.
Это то, с чем я столкнулся, предполагая, что мы используем NSPredicate
, а theres нет первичного уникального ключа, это самый лучший ответ, который я думаю с наименьшими издержками.
- Установите
NSFetchRequest
на NSManagedObjectID
. Выключите все, чтобы минимизировать накладные расходы.
- Выполнить запрос на выборку с помощью желаемого предиката , Не использовать FetchLimit.
-
Из полученного массива NSManagedObjectID
. получите случайное число объектов. это хорошее решение: Получить n случайных объектов (например, 4) из nsarray
-
Теперь у вас есть случайный NSManagedObjectIDs
вашего желаемого счета (более или менее случайный)
- Прокрутите массив случайных объектов и используйте
NSManagedObjectContext objectWithID:
для получения объектов.
Ответ 4
Если вы все равно загружаете все объекты, нет необходимости в первом запросе получить счет объекта. Вы можете просто использовать что-то вроде:
myEntityCount = [myEntities count]
Ответ 5
Решение, предложенное Core, не будет работать, если вам нужно рандомизировать выборку в строках таблицы подмножества, ограниченных предикатом (например, "где-то что-то" ).
Лучшее решение, которое у меня есть до сих пор (где мне не нужно загружать все или большое количество строк), использует случайный выбор на основе первичного ключа (конечно, для него требуется первичный ключ в таблице, предпочтительно без учета любые отсутствующие значения).