2016-02-26 52 views

回答

2

這是我覺得看起來或多或少不錯的東西,但效率不高,因爲它可以:

yourCollection asSet asOrderedCollection shuffled first: numberOfElements 
+0

非常優雅。我可以看到提高效率(通常不會成爲問題,但有些人會掛在上面......)的唯一方法就是將_indices_而不是集合(因爲索引會更少) ,然後使用類似'#atAll:'的東西來從集合中挑選那些隨機化的索引(如果你想要它們,你仍然需要'#asSet' _distinct_)。 –

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 

一些言論

  • 顯式生成器:它明確地使用給定的生成器,即,我稱之爲aGeneratorRandom的實例。出於數學原因,如果您正在爲您的應用程序獲取樣品,則所有這些應該在整個程序中使用相同的生成器。此外,這將爲您帶來額外的好處:保存並稍後恢復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 

UPDATE

下面是另一種方法:

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

嗯,我喜歡「byo generator」的方法,但是如果收集和樣本量很大,那麼您可能會等待很長一段時間,直到發生器最終選擇一個「空閒」數字。 –

+0

@ AmosM.Carpenter好點。我使用的是更接近第二種方法。 –

+1

對不起,你應該挑剔,但不應該使用'#removeIndex:' - 它意味着是私人的。使用公共方法'#removeAt:'相反可以回答已刪除的元素,這意味着您可以擺脫額外的'element'臨時變量(即,只需執行'sample add:(aCollection removeAt:index)') 。這兩個「刪除」方法都在OrderedCollection上,所以這不適用於其他類型的集合。 –

相關問題