【问题标题】:How to easily shuffle a list in sml?如何轻松打乱 sml 中的列表?
【发布时间】:2014-12-02 08:09:29
【问题描述】:

如何轻松地打乱 sml 中的元组列表?似乎没有任何内置功能可以这样做。

我假设我需要使用随机数生成器,但我不知道如何移动列表中的项目。

【问题讨论】:

    标签: list random sml shuffle smlnj


    【解决方案1】:

    这是给Moscow ML's Random library的。对于SML/NJ's Random library,你需要稍微调整一下随机函数。

    val _ = load "Random"
    val rng = Random.newgen ()
    
    (* select([5,6,7,8,9], 2) = (7, [5,6,8,9]) *)
    fun select (y::xs, 0) = (y, xs)
      | select (x::xs, i) = let val (y, xs') = select (xs, i-1) in (y, x::xs') end
      | select (_, i) = raise Fail ("Short by " ^ Int.toString i ^ " elements.")
    
    (* Recreates a list in random order by removing elements in random positions *)
    fun shuffle xs =
        let fun rtake [] _ = []
              | rtake ys max =
                let val (y, ys') = select (ys, Random.range (0, max) rng)
                in y :: rtake ys' (max-1)
                end
        in rtake xs (length xs) end
    

    【讨论】:

    • 我尝试修改它以使用内置的 Random 库,但出现错误:未捕获的异常匹配 [nonexhaustive match failure] 位于此行:| select (x::xs, i) = let val (y, xs') = select (xs, i-1) in (y, x::xs') end
    • 当这种情况发生时,这意味着你已经为 i >= length xs 调用了select(xs, i)。当Random.range (0, max) rng 被调用时,它会在区间 [0,max) 中生成一个值(即不计算 max 本身)。 SML/NJ 的 Random.randRange 使用包含区间,这意味着您需要从最大值中减去 1:Random.randRange (0, max-1) rng。否则,随机数生成器会偶尔生成一个太大的数字。
    猜你喜欢
    • 1970-01-01
    • 2011-12-21
    • 2014-06-04
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    相关资源
    最近更新 更多