2016-08-31 54 views
2

我正在開發一個項目,需要我編寫一個函數來從一組中選擇指定數量的隨機元素。然後將這些元素映射到一個變量供以後比較。F#一組隨機元素<string>

所以在我的場景中,我必須選擇任何給定集的5%。

let rec randomSet (a:Set<string>) = 
let setLength = (a.Count/100) * 5 

let list = [] 
let rand = System.Random 
if set.Length <> setLength then 
    // some code will go here 
    randomSet setLength eIDS 
else 
    set 

^請批評我的代碼,我只正在F#編碼了一個星期。

我試圖遞歸地做,但我有一種感覺,這是錯誤的方式去。我嘗試了其他方法,但他們使用.take函數,因此每次返回的集合都是相同的。

任何想法?我並不是在一套元素之後的一個元素之後,我是在任何一套元素之後的5%之後。

這不是同樣的問題:如果你覺得是,請解釋How can I select a random value from a list using F#

+0

如果效率:

let r = System.Random() let fivePercent _ = r.NextDouble() < 0.05 

您現在可以使用謂詞篩選集合是一個問題,你可能想看看[水庫採樣](https://en.wikipedia.org/wiki/Reservoir_sampling)。 – kvb

回答

3

有多種方法可以做到這一點。根據輸入中元素的數量和要挑選的項目數量,不同的策略可能會更有效。

也許最簡單的方法是通過一個隨機數到輸入進行排序,然後使用take獲得所需要的數目的元素:

let data = [| 0 .. 1000 |] 

let rnd = System.Random() 

data 
|> Seq.sortBy (fun _ -> rnd.Next()) 
|> Seq.take 50 

這將隨機排序的序列(其可以是用於大序列慢),但是它恰好需要你想要的元素的數量(不同於馬克的解決方案,它將返回約5%的項目)。

如果您想從大列表中選擇小數字,最好隨機生成索引(確保沒有重複項),然後根據索引進行直接查找。

+0

謝謝。我嘗試了我的程序中的代碼,並且有近3000個項目對速度影響不大,爲已經2分鐘的長時間增加了額外的20秒。我的兄弟昨天也給我買了你的書,我期待着閱讀它。 –

3

由於Set<'a>工具Seq<'a>,這個問題是,事實上,How can I select a random value from a list using F#重複所有你需要做的就是重新洗牌的設置,採取的第一個5%的元素,並把它放回了一套。

儘管它的樂趣,但這是另一種解決方案。如果您需要挑選5%,那麼首先定義返回true只有它被稱爲時代的5%謂詞:

let randomlySelectedSubset = stringSet |> Seq.filter fivePercent |> set 
+0

我很抱歉,我應該說,我不明白這是同一個問題。我是F#的新手,但對集合或序列沒有太多經驗。我會採取你在船上所說的話,並把更多的時間放在他們身上。 –

+1

也謝謝。 –

+0

如果速度是一個問題,這就是贏家;-) –