简体   繁体   English

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

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

With a list of integers such as: 使用整数列表,例如:

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

How can I create a list of list of ints from the above, with all new lists the same specified length? 如何从上面创建一个int列表列表,所有新列表都具有相同的指定长度?

For example, I need to go from: 例如,我需要从:

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

with the number to split being 3? 分数为3?

Thanks for your time. 谢谢你的时间。

So what you actually want is a function of type 所以你真正想要的是类型的功能

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

that takes a list of integers and a sub-list-size. 它采用整数列表和子列表大小。 How about one that is even more general? 一个更普遍的怎么样?

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

Here comes the implementation: 这是实现:

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]

Please let me know if you get extra points for this! 如果你有额外的积分,请告诉我! ;) ;)

The code you give is a way to remove a given number of elements from the front of a list. 您提供的代码是一种从列表前面删除给定数量元素的方法。 One way to proceed might be to leave this function as it is (maybe clean it up a little) and use an outer function to process the whole list. 一种方法可能是保持这个功能不变(可能会稍微清理一下)并使用外部函数来处理整个列表。 For this to work easily, your function might also want to return the remainder of the list (so the outer function can easily tell what still needs to be segmented). 为了使其易于使用,您的函数可能还希望返回列表的其余部分(因此外部函数可以轻松地告诉仍需要分段的内容)。

It seems, though, that you want to solve the problem with a single function. 但是,似乎您想用单个函数解决问题。 If so, the main thing I see that's missing is an accumulator for the pieces you've already snipped off. 如果是这样的话,我发现缺少的主要是你已经剪掉的碎片的累加器。 And you also can't quit when you reach your count, you have to remember the piece you just snipped off, and then process the rest of the list the same way. 当你达到计数时你也不能退出,你必须记住你刚刚剪掉的那一块,然后以同样的方式处理列表的其余部分。

If I were solving this myself, I'd try to generalize the problem so that the recursive call could help out in all cases. 如果我自己解决这个问题,我会尝试概括问题,以便递归调用可以在所有情况下都有所帮助。 Something that might work is to allow the first piece to be shorter than the rest. 可能有用的东西是让第一件比其他件短。 That way you can write it as a single function, with no accumulators (just recursive calls). 这样你就可以把它写成一个单独的函数,没有累加器(只是递归调用)。

I would probably do it this way: 我可能会这样做:

    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

Note that we are being lenient if n doesn't divide List.length lst evenly. 请注意,如果n不均匀地除List.length lst ,我们就是宽松的。 Example: split [1;2;3;4;5] 2 gives [[1;2];[3;4];[5]] 示例: split [1;2;3;4;5] 2给出[[1;2];[3;4];[5]]

Final note: the code is very verbose because the OCaml standard lib is very bare bones :/ With a different lib I'm sure this could be made much more concise. 最后注意:代码非常冗长,因为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