How can I select a random value from a list using F#

前端 未结 3 2076
独厮守ぢ
独厮守ぢ 2020-12-18 01:17

I\'m new to F# and I\'m trying to figure out how to return a random string value from a list/array of strings.

I have a list like this:



        
3条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-18 01:40

    I wrote a blog post on exactly this topic a while ago: http://latkin.org/blog/2013/11/16/selecting-a-random-element-from-a-linked-list-3-approaches-in-f/

    3 approaches are given there, with discussion of performance and tradeoffs of each.

    To summarize:

    // pro: simple, fast in practice
    // con: 2-pass (once to get length, once to select nth element)
    let method1 lst (rng : Random)  =
        List.nth lst (rng.Next(List.length lst))
    
    // pro: ~1 pass, list length is not bound by int32
    // con: more complex, slower in practice
    let method2 lst (rng : Random) =
        let rec step remaining picks top =
            match (remaining, picks) with
            | ([], []) -> failwith "Don't pass empty list"
            //  if only 1 element is picked, this is the result
            | ([], [p]) -> p
            // if multiple elements are picked, select randomly from them
            | ([], ps) -> step ps [] -1
            | (h :: t, ps) ->
                match rng.Next() with
                // if RNG makes new top number, picks list is reset
                | n when n > top -> step t [h] n
                // if RNG ties top number, add current element to picks list
                | n when n = top -> step t (h::ps) top
                // otherwise ignore and move to next element
                | _ -> step t ps top
        step lst [] -1
    
    // pro: exactly 1 pass
    // con: more complex, slowest in practice due to tuple allocations
    let method3 lst (rng : Random) =
        snd <| List.fold (fun (i, pick) elem ->
                   if rng.Next(i) = 0 then (i + 1, elem)
                   else (i + 1, pick)
               ) (0, List.head lst) lst
    

    Edit: I should clarify that above shows a few ways to get a random element from a list, assuming you must use a list. If it fits with the rest of your program's design, it is definitely more efficient to take a random element from an array.

提交回复
热议问题