List 只需要选择列表中的一些随机元素,并在OCaml中返回它们

List 只需要选择列表中的一些随机元素,并在OCaml中返回它们,list,random,functional-programming,ocaml,List,Random,Functional Programming,Ocaml,我想在列表l中选择n个不同的随机元素,并在choose_元素中返回它们,但对于足够大的列表,我有一个StackOverFlow错误 我试图使用tail\u递归函数choose\elem\u aux来实现这一点,但我认为我的condition List.mem在复杂性方面不够有效! 我通常在其他编程语言中使用布尔标记数组来实现这一点,我将生成的每个随机数的索引标记为true! 但我不能在OCaml中这样做,因为我不能在if或else块中执行多条指令!像这样: ... else { mark[r]

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

我试图使用tail\u递归函数choose\elem\u aux来实现这一点,但我认为我的condition 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 ;;

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

如果条件允许,则开始 指示1; 说明2; * ... * 终止 否则开始 * ... * 终止 开始*..*“结束块”的作用与括号相同,因此您也可以只插入括号:

如果情况如此 指示1; 说明2; * ... * 其他的 * ... * 因此,您可以很好地进行优化

这里发生的事情是,在ocaml中编写if b然后t else f时,您正在构建一个类型为t if t:t和f:t的值。 例如,您可以编写if b然后0或者if b然后Hello else再见。 它还适用于大多数指令类型的单元类型:

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表达式也有类型单位。

多亏了@théo-winterhalter 我只是这样想:

让rec选择标记tmp的辅助元素= 如果n=0,则tmp 其他的 设r=Random.int长度l,如果标记为.r,则 选择辅助标记tmp else mark.r