الحصول على مجموعة فرعية عشوائية من مجموعة في F #
سؤال
أحاول التفكير في طريقة أنيقة للحصول على مجموعة فرعية عشوائية من مجموعة في F #
اي افكار في هذا؟
ربما هذا سيعمل: قل لدينا مجموعة من 2عاشر العناصر ونحن بحاجة إلى اختيار مجموعة فرعية من العناصر. ثم إذا استطعنا إنشاء رقم عشوائي بحجم X يحتوي على Y 2ن صلاحيات لدينا قناع عشوائي بفعالية مع ثقوب ص في ذلك. يمكننا الاستمرار في توليد أرقام عشوائية جديدة حتى نحصل على أول واحد يرضي هذا القيد ولكن هل هناك طريقة أفضل؟
المحلول
إذا كنت لا ترغب في التحويل إلى صفيف، فيمكنك فعل شيء مثل هذا. هذا هو O (n * m) حيث M هو حجم المجموعة.
open System
let rnd = Random(0);
let set = Array.init 10 (fun i -> i) |> Set.of_array
let randomSubSet n set =
seq {
let i = set |> Set.to_seq |> Seq.nth (rnd.Next(set.Count))
yield i
yield! set |> Set.remove i
}
|> Seq.take n
|> Set.of_seq
let result = set |> randomSubSet 3
for x in result do
printfn "%A" x
نصائح أخرى
أتفق مع ovenhannesrossel. هناك خوارزمية F # خلط ورق اللعب هنا يمكنك تعديل مناسب. قم بتحويل المجموعة إلى صفيف، ثم حلقة حتى حددت كافية من العناصر العشوائية عن المجموعة الفرعية الجديدة.
عدم وجود فهم جيد حقا من F # وما الذي يمكن اعتباره أنيقا هناك، يمكنك فقط إجراء خلط ورق اللعب على قائمة العناصر وحدد الأول ذ. أ فيشر ييتس خلط ورق اللعب حتى يساعدك في هذا الصدد كما تحتاج فقط إلى خلط ورق اللعب Y. عناصر.
rnd يجب أن يكون خارج وظيفة الفرع الفرعي.
let rnd = new Random()
let rec subset xs =
let removeAt n xs = ( Seq.nth (n-1) xs, Seq.append (Seq.take (n-1) xs) (Seq.skip n xs) )
match xs with
| [] -> []
| _ -> let (rem, left) = removeAt (rnd.Next( List.length xs ) + 1) xs
let next = subset (List.of_seq left)
if rnd.Next(2) = 0 then rem :: next else next
هل تعني مجموعة فرعية عشوائية من أي حجم؟
لحالة مجموعة فرعية عشوائية من حجم معين، هناك إجابة أنيقة للغاية هنا:
حدد عناصر عشوائية من قائمةu003CT> في ج #
هنا في pseudocode:
RandomKSubset(list, k):
n = len(list)
needed = k
result = {}
for i = 0 to n:
if rand() < needed / (n-i)
push(list[i], result)
needed--
return result
باستخدام Seq.Pold للبناء باستخدام التقييم الكسول عشوائي مجموعة فرعية:
let rnd = new Random()
let subset2 xs = let insertAt n xs x = Seq.concat [Seq.take n xs; seq [x]; Seq.skip n xs]
let randomInsert xs = insertAt (rnd.Next( (Seq.length xs) + 1 )) xs
xs |> Seq.fold randomInsert Seq.empty |> Seq.take (rnd.Next( Seq.length xs ) + 1)