【问题标题】:Just want choose some random elements of a list and return them in OCaml只想选择列表中的一些随机元素并在 OCaml 中返回它们
【发布时间】:2019-10-23 13:40:45
【问题描述】:

我想在 l 列表中选择 n 不同的随机元素并将它们返回到 choose_elements 但对于足够大的列表我有一个 StackOverFlow 错误!

我尝试使用 tail_recursive 函数 choose_elem_aux 来做到这一点,但我认为我的条件 List.mem 在复杂性方面不够高效! 我通常在其他编程语言中使用布尔标记数组执行此操作,我标记在true 中生成的每个随机数的索引! 但我不能在 OCaml 中执行此操作,因为我无法在 if 或 else 块中执行多条指令!像这样:

... else {
mark[r] =true ;
choose_elem_aux l n mark tmp ;
} ...


let choose l = 
  nth l (Random.int (List.length l)) ;;

let rec choose_elem_aux l n tmp =
  if n=0 then tmp
  else
    let r=choose l in if List.mem r tmp then
      choose_elem_aux l n tmp else choose_elem_aux l (n-1) (r::tmp) ;;

let rec choose_elements l n = 
  choose_elem_aux l n [] ;;

StackOverflow 用于大型列表,例如:

choose_elements [1...10_000] 7 ;;

【问题讨论】:

    标签: list random functional-programming ocaml


    【解决方案1】:

    首先,ocaml 确实允许您在 if then else 中编写多个语句,只是它不像 C 语言那样编写。

    if condition then begin
      instruction1 ;
      instruction 2 ;
      (* ... *)
    end
    else begin
      (* ... *)
    end
    

    begin (* ... *) end 块的工作方式与括号相同,因此您也可以只使用括号:

    if condition then (
      instruction1 ;
      instruction 2 ;
      (* ... *)
    )
    else (
      (* ... *)
    )
    

    所以你可以做你的优化就好了。

    这里发生的情况是,当在 ocaml 中写入 if b then t else f 时,如果 t : Tf : T,则您正在构建类型为 T 的值。 例如,您可以写 if b then 0 else 1if b then "Hello" else "Goodbye"。 它也适用于unit 类型(大多数指令的类型):

    if b then instruction1 else instruction2
    

    分号运算符允许顺序执行两条指令:

    (;) : unit -> unit -> unit
    

    请注意,它与在大多数语言中标记指令结束的地方不同。

    问题是当你写的时候

    if b then instruction1 else instruction2 ; instruction 3
    

    不理解为

    if b then instruction1 else (instruction2 ; instruction 3)
    

    如你所愿,但如你所愿

    (if b then instruction1 else instruction2) ; instruction 3
    

    这也是有道理的,因为if 表达式也有unit 类型。

    【讨论】:

      【解决方案2】:

      感谢@théo-winterhalter 我就是这样对它的:

      let rec choose_elem_aux l n mark tmp =
        if n=0 then tmp
        else
          let r=Random.int (length l) in if mark.(r) then
            choose_elem_aux l n mark tmp else (mark.(r) <- true ;
                     choose_elem_aux l (n-1) mark ((nth l r)::tmp) ;);;
      
      let rec choose_elements l n = 
        let mark = Array.make (length l) false in
        choose_elem_aux l n mark [] ;;
      

      【讨论】:

        猜你喜欢
        • 2012-03-12
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 2013-10-19
        • 1970-01-01
        • 2023-01-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多