繁体   English   中英

Ocaml列表的int列表(相反的扁平化)

[英]Ocaml list of ints to list of int lists (Opposite of flattening)

使用整数列表,例如:

[1;2;3;4;5;6;7;8;9]

如何从上面创建一个int列表列表,所有新列表都具有相同的指定长度?

例如,我需要从:

[1;2;3;4;5;6;7;8;9] to [[1;2;3];[4;5;6];[7;8;9]]

分数为3?

谢谢你的时间。

所以你真正想要的是类型的功能

val split : int list -> int -> int list list

它采用整数列表和子列表大小。 一个更普遍的怎么样?

val split : 'a list -> int -> 'a list list

这是实现:

let split xs size =
  let (_, r, rs) =
    (* fold over the list, keeping track of how many elements are still
       missing in the current list (csize), the current list (ys) and
       the result list (zss) *) 
    List.fold_left (fun (csize, ys, zss) elt ->
      (* if target size is 0, add the current list to the target list and
         start a new empty current list of target-size size *)
      if csize = 0 then (size - 1, [elt], zss @ [ys])
      (* otherwise decrement the target size and append the current element
         elt to the current list ys *)
      else (csize - 1, ys @ [elt], zss))
      (* start the accumulator with target-size=size, an empty current list and
         an empty target-list *)
        (size, [], []) xs
  in
  (* add the "left-overs" to the back of the target-list *)
  rs @ [r]

如果你有额外的积分,请告诉我! ;)

您提供的代码是一种从列表前面删除给定数量元素的方法。 一种方法可能是保持这个功能不变(可能会稍微清理一下)并使用外部函数来处理整个列表。 为了使其易于使用,您的函数可能还希望返回列表的其余部分(因此外部函数可以轻松地告诉仍需要分段的内容)。

但是,似乎您想用单个函数解决问题。 如果是这样的话,我发现缺少的主要是你已经剪掉的碎片的累加器。 当你达到计数时你也不能退出,你必须记住你刚刚剪掉的那一块,然后以同样的方式处理列表的其余部分。

如果我自己解决这个问题,我会尝试概括问题,以便递归调用可以在所有情况下都有所帮助。 可能有用的东西是让第一件比其他件短。 这样你就可以把它写成一个单独的函数,没有累加器(只是递归调用)。

我可能会这样做:

    let split lst n =
      let rec parti n acc xs = 
        match xs with 
        | []              -> (List.rev acc, [])
        | _::_ when n = 0 -> (List.rev acc, xs)
        | x::xs -> parti (pred n) (x::acc) xs
      in let rec concat acc = function
        | [] -> List.rev acc
        | xs -> let (part, rest) = parti n [] xs in concat (part::acc) rest
      in concat [] lst

请注意,如果n不均匀地除List.length lst ,我们就是宽松的。 示例: split [1;2;3;4;5] 2给出[[1;2];[3;4];[5]]

最后注意:代码非常冗长,因为OCaml标准库非常简单:/使用不同的lib我相信这可以更加简洁。

let rec split n xs =
  let rec take k xs ys = match k, xs with
    | 0, _ -> List.rev ys :: split n xs
    | _, [] -> if ys = [] then [] else [ys]
    | _, x::xs' -> take (k - 1) xs' (x::ys)
  in take n xs []

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM