2010-05-13 13 views
10

का उपयोग करके एक यादृच्छिक इकाई उदाहरण प्राप्त करना एक ऐप पर काम करना जहां मेरे पास प्रबंधित ऑब्जेक्ट्स का एक बड़ा संग्रह है जिसके विरुद्ध मैं कुछ यादृच्छिक उदाहरण प्राप्त करना चाहता हूं।आईफ़ोन ओएस: NSPredicate Nsfetchrequest और कोर डेटा

मेरा सवाल यह है कि, क्या मैं किसी भी तरह से एनएसपीडिकेट और NSFetchRequest का उपयोग यादृच्छिक रूप से कई वस्तुओं को वापस करने के लिए कर सकता हूं।

मैंने देखा कि आप वास्तव में डेटा मॉडलर का उपयोग करके इकाई में NSFetchRequest जोड़ सकते हैं, इसका उपयोग करके यादृच्छिक fetch करने के किसी भी तरीके से?

तालिका के "गिनती" को निर्धारित करने के लिए सबसे अच्छी विधि क्या होगी ताकि मैं यादृच्छिक संख्या जेनरेटर की सीमा निर्धारित कर सकूं।

यदि आपको अधिक जानकारी चाहिए तो मुझे बताएं।

धन्यवाद!

निक

+0

अतिरिक्त जानकारी: जिन चीज़ों को मैं पकड़ने की कोशिश कर रहा हूं वे दो गुणों के साथ ऑब्जेक्ट्स हैं, 1-50 वर्णों से कहीं भी एक एनएसस्ट्रिंग, और एक छद्म प्राथमिक कुंजी int मैंने सोचा था कि यादृच्छिक चयन बिट में मदद मिल सकती है। मैं मॉडल को पुन: व्यवस्थित कर सकता हूं, हालांकि यदि आवश्यक हो तो भी इस चूसने वाले को प्रोटोटाइप करना। – nickthedude

+0

यह टिप्पणी आपके प्रश्न में जोड़ा जाना चाहिए। –

उत्तर

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 

आप प्रतिस्थापन के बिना नमूने के लिए, डुप्लिकेट को खत्म करने की जरूरत है, तो आप शायद अपने शीर्षक में या अपने कार्यान्वयन फ़ाइल के शीर्ष पर

कहीं randomEntityIndexNSNumber ऑब्जेक्ट्स को केवल यादृच्छिक int एस नमूना देने के बजाय बनाएं।

इस मामले में, एक आदेश दिया NSSet से नमूना, के रूप में आप उन्हें बैग से बाहर निकालते हैं और सेट से एक यादृच्छिक NSNumber वस्तु उठा के प्रयोजनों के लिए myEntityCount घटती NSNumber वस्तुओं को हटा दें।

+0

अरे एलेक्स बहुत बहुत धन्यवाद, बहुत अच्छा! ऐसा लगता है कि यह पूरी तरह से काम करना चाहिए। मेरी एकमात्र चिंता यह है कि myEntities सरणी में 3k-5k उदाहरणों से कहीं भी शामिल होगा, यहां तक ​​कि डेटा के कई टुकड़े भी आप सोच रहे हैं कि यह बहुत धीमी गति से नहीं मिलेगा? मैं आदर्श रूप से हर इकाई उदाहरण को पकड़ने के बिना यादृच्छिक चयन करने की उम्मीद कर रहा था, क्या मैं यहां गलत पेड़ को भड़क रहा हूं? फिर से धन्यवाद एलेक्स! – nickthedude

+0

अतिरिक्त जानकारी: जिन चीजों को मैं पकड़ने की कोशिश कर रहा हूं वे दो गुणों के साथ ऑब्जेक्ट्स हैं, 1-50 वर्णों से कहीं भी एक एनएसस्ट्रिंग, और एक छद्म प्राथमिक कुंजी int मैंने सोचा था कि यादृच्छिक चयन बिट में मदद मिल सकती है। मैं मॉडल को पुन: व्यवस्थित कर सकता हूं, हालांकि यदि आवश्यक हो तो भी इस चूसने वाले को प्रोटोटाइप करना। – nickthedude

+0

आप सभी रिकॉर्ड्स को पकड़ने के बजाय निश्चित रूप से छद्म-प्राथमिक-कुंजी विशेषता का उपयोग कर सकते हैं। –

0

यदि आप सभी वस्तुओं को वैसे भी ला रहे हैं, तो ऑब्जेक्ट गिनती प्राप्त करने के पहले अनुरोध की आवश्यकता नहीं है।

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]; 
19

: तुम बस की तरह कुछ का उपयोग कर सकते यदि आपको किसी सबसेट तालिका पंक्तियों के भीतर लाने के लिए यादृच्छिक करने की आवश्यकता है, तो एक अनुमान के अनुसार प्रतिबंधित (उदाहरण के लिए "जहां कुछ < कुछ")।

मेरे पास अब तक का सबसे अच्छा समाधान है (जहां मुझे सभी या बड़ी संख्या में पंक्तियां लाने की आवश्यकता नहीं है) प्राथमिक कुंजी के आधार पर यादृच्छिक रूप से चयन का उपयोग कर रहा है (बेशक तालिका में प्राथमिक कुंजी की आवश्यकता होती है, अधिमानतः w/ओ किसी भी गुम मूल्य)।

+3

मैंने यादृच्छिक वस्तु लाने की इस विधि को आजमाया क्योंकि मैंने सोचा था कि यह एक यादृच्छिक वस्तु को खींचने के लिए 5k से अधिक प्रविष्टियों की अपनी पूरी सूची को फिर से लाने से बहुत कम ओवरहेड होगा। हालांकि, मुझे जो मिला वह यह था कि कोई ऑफसेट नहीं था कि मैं हमेशा एक ही दस या इतनी प्रबंधित वस्तुओं में से एक को वापस प्राप्त करूंगा। यादृच्छिक वस्तुओं को उत्पन्न करने की यह विधि किसी भी तरह से 'यादृच्छिक' नहीं थी और इस प्रकार, मेरे उपयोग के लिए, अस्वीकार्य। स्वीकार किए गए उत्तर का पालन करने से उपरांत कम से कम था, कम से कम मैंने सोचा था। इसके कारण, मैं इस पर स्वीकृत उत्तर की सिफारिश करता हूं। – Krejko

+0

मुझे इसके साथ भी परेशानी हो रही है ... मुझे अपने मूल डेटा उदाहरणों से एक यादृच्छिक वस्तु प्राप्त करने की आवश्यकता है और कोरी फ़्लॉइड के मुकाबले लगभग एक ही विधि बनाई गई है, लेकिन ऐसा लगता है कि कोरडाटा पसंद नहीं करता है और ऐसा कुछ ऐसा लगता है जो कोरडाटा पसंद नहीं करता है और यह अपेक्षित परिणाम वापस नहीं करता है ... –

+0

+1 इस उत्तर के लिए, लेकिन इसे एक छोटे से फिक्स की आवश्यकता है, जब गणना ऑफसेट myEntityCount के बराबर हो जाता है, तो कम से कम मेरे मामले में, शून्य शून्य रिकॉर्ड लौटाएगा, इसलिए मैंने 1 घटा दिया गणना ऑफसेट से। फिर आपको एक और छोटी जांच की आवश्यकता है -> अगर myEntityCount शून्य है तो आपको वास्तव में कोई भी परिणाम नहीं मिल सकता है, तो ऑफ़सेट की गणना करने से पहले आपको विधि से बाहर निकलने की आवश्यकता है। – cybercow

0

समाधान कोर द्वारा सुझाए गए कार्य नहीं करेगा: इसके बजाय कि जिस तरह से आप कुशलतापूर्वक स्मृति में केवल एक इकाई प्राप्त कर सके fetchOffset साथ संयोजन के रूप में fetchLimit का उपयोग

myEntityCount = [myEntities count] 
2

मैंने इसके लिए बहुत कुछ खोजा है, अनिवार्य रूप से कोरेडाटा आपको कोई यादृच्छिक पंक्ति नहीं देगा, और इसका मतलब यह नहीं है। आपको अपना खुद का बनाना है।

यह है कि मैं यह मानता हूं कि हम NSPredicate का उपयोग कर रहे हैं और कोई प्राथमिक अनोखा कुंजी नहीं है, यह सबसे अच्छा संभव उत्तर है जो मुझे कम से कम ओवरहेड के साथ लगता है।

  1. NSFetchRequestNSManagedObjectID पर सेट करें। ओवरहेड को कम करने के लिए सब कुछ बंद करें।
  2. अपने वांछित के साथ fetch अनुरोध निष्पादित करें, किसी भी FetchLimit का उपयोग न करें।
  3. प्राप्त NSManagedObjectID सरणी से। वस्तुओं की यादृच्छिक संख्या प्राप्त करें। Get n random objects (for example 4) from nsarray

  4. अब आप यादृच्छिक मिल गया है अपने वांछित गिनती, (जो कम या ज्यादा यादृच्छिक कर रहे हैं)

  5. यादृच्छिक objectId सरणी के माध्यम से लूप के NSManagedObjectIDs और NSManagedObjectContext objectWithID: का प्रयोग करें वस्तुओं को पाने के लिए: यह एक अच्छा उपाय है।
संबंधित मुद्दे