2016-02-26 8 views
6

मैं संग्रह से विशिष्ट, यादृच्छिक तत्वों का एक विशिष्ट संख्या (> 1) कैसे सुंदरता से प्राप्त कर सकता हूं?स्मॉलटॉक में संग्रह से यादृच्छिक तत्वों की एक विशिष्ट संख्या कैसे प्राप्त करें?

उत्तर

2

यह कुछ मैं दिखता है और अधिक या कम अच्छा लगता है कि है, लेकिन के रूप में कुशल के रूप में यह हो सकता है नहीं है:

yourCollection asSet asOrderedCollection shuffled first: numberOfElements 
+0

बहुत ही सुरुचिपूर्ण। दक्षता में सुधार करने के लिए एकमात्र तरीका मैं देख सकता था (जो आम तौर पर कोई मुद्दा नहीं होगा, लेकिन कुछ लोग इसे लटकाते हैं ...) संग्रह के बजाय _indices_ को घुमाएंगे (क्योंकि कम सूचकांक होंगे) , और फिर उन यादृच्छिक इंडेक्स को एक सेट से बाहर लेने के लिए '#atAll:' जैसे कुछ का उपयोग करें (यदि आपको उन्हें _distinct_ चाहिए तो भी आपको अभी भी '# asSet' की आवश्यकता होगी)। –

5

पर विचार करें निम्नलिखित कोड का टुकड़ा

sample: anInteger from: aCollection using: aGenerator 
    | sample | 
    sample := Set new: anInteger. 
    [sample size = anInteger] 
    whileFalse: [ | element | 
     element := aCollection atRandom: aGenerator. 
     sample add: element]. 
    ^sample asArray 

कुछ टिप्पणियों

  • स्पष्ट जेनरेटर: यह स्पष्ट रूप से दिए गए जनरेटर का उपयोग करता है, यानी Random का एक उदाहरण, जिसे मैंने aGenerator कहा है। गणितीय कारणों के लिए, यदि आपको अपने आवेदन के लिए नमूने मिल रहे हैं, तो उन सभी को आपके कार्यक्रम में एक ही जनरेटर का उपयोग करना चाहिए। इसके अलावा यह आपको एक अतिरिक्त लाभ देगा: सहेजें और बाद में seed को पुनर्स्थापित करें और आप अपने सिस्टम के पिछले "यादृच्छिक" व्यवहार को पुन: उत्पन्न करने में सक्षम होंगे, जो परीक्षण के लिए अच्छा है।

  • उपलब्धता के लिए कोई जांच: कोड की जाँच नहीं है कि यह वांछित नमूना है, इस स्थिति हो सकता है अगर aCollection कम से कम anInteger अलग तत्व नहीं प्राप्त करने के लिए संभव है।

  • वर्गहीन कोड: विधि कुछ वर्ग के पास जाना चाहिए।

उदाहरण के लिए:

Random >> sample: anInteger from: aCollection 
    | sample | 
    sample := Set new: anInteger. 
    [sample size = anInteger] 
    whileFalse: [ | element | 
     element := aCollection atRandom: self. 
     sample add: element]. 
    ^sample asArray 

अद्यतन

यहाँ एक और तरीका है:

Random >> remove: anInteger from: aCollection 
    | sample | 
    sample := OrderedCollection new: anInteger. 
    anInteger timesRepeat: [| index element | 
    index := aCollection size atRandom: self. 
    element := aCollection removeAt: index. 
    sample add: element]. 
    ^sample 

टिप्पणी

आमतौर पर ऐसा होता है कि जब हम पुनरावृत्ति के बिना नमूना करना चाहते हैं तो हम संग्रह से तत्वों को भी हटाना चाहते हैं क्योंकि हम उन्हें यादृच्छिक रूप से चुनते हैं। इन मामलों में अक्सर ऐसा होता है कि संग्रह को दोहराव नहीं माना जाता है।

+1

हम्म, मुझे "बायो जनरेटर" दृष्टिकोण पसंद है, लेकिन यदि संग्रह और नमूना आकार बड़ा है, तो आप अंत में थोड़ी देर इंतजार कर सकते हैं जब तक जनरेटर अंत में "मुक्त" संख्या नहीं चुनता। –

+0

@ AmosM.Carpenter अच्छा बिंदु। मैं जो भी उपयोग करता हूं वह दूसरे दृष्टिकोण के करीब है। –

+1

नाइटपीकी होने के लिए खेद है, लेकिन आपको '#removeIndex:' का उपयोग नहीं करना चाहिए - यह निजी होना है। सार्वजनिक विधि का उपयोग करना '#removeAt:' इसके बजाय हटाए गए तत्व का उत्तर देने का अतिरिक्त लाभ होगा, जिसका अर्थ है कि आप अतिरिक्त 'तत्व' अस्थायी चर से छुटकारा पा सकते हैं (यानी केवल 'नमूना जोड़ें: (aCollection removeAt: index) ') ।उन "निकालें" विधियां 'ऑर्डर्ड कोलेक्शन' पर हैं, इसलिए यह अन्य प्रकार के संग्रहों के साथ काम नहीं करेगी। –

संबंधित मुद्दे