الحصول على مجموعة فرعية عشوائية من مجموعة في F #

StackOverflow https://stackoverflow.com/questions/1123958

  •  13-09-2019
  •  | 
  •  

سؤال

أحاول التفكير في طريقة أنيقة للحصول على مجموعة فرعية عشوائية من مجموعة في 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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top