2012-11-07 47 views
2

用整数,如清单:ocaml的名单

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

如何创建整数列表列表从以上,所有新名单相同的指定长度?

例如,我需要去:

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

编号为分割为3?

谢谢你的时间。

+4

这看起来像家庭作业。如果是,请显示您尝试的一些代码,并描述您尝试时出了什么问题。 –

+0

我有得到多个元件出的方式,如下所示: '让REC ITER listIn numAt COL输出= 如果(numAt MOD(COL + 1))= 0,那么 输出 别的 开始 \t匹配listIn与 \t [] - > [] \t | X :: XS - >(ITER XS(numAt + 1)山口(输出@ [X])) 结束' 但找到一种方法,这种输出组合成一个列表的列表很努力。 – user1804784

+0

谷歌搜索词是“滑动窗口”或移动窗口 –

回答

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] 

请让我知道,如果你为此获得额外加分! ;)

+0

我刚碰到一个bug:当调用split [1; 2; 3; 4; 5; 6; 7; 8; 9] 3时此代码行为不正确';它产生'[[1; 2; 3]; [4; 5; 6; 7]; [8; 9]]'。 –

+1

谢谢亚历克斯 - 我修正了错误! – lambdapower

2

您给出的代码是一种从列表前面删除给定数量元素的方法。一种进行的方式可能是保持原样(可能会清理一些)并使用外部函数来处理整个列表。为了方便起见,你的函数可能还想返回列表的其余部分(所以外部函数可以很容易地告诉还需要分割的东西)。

看来,虽然你想用单一功能解决问题。如果是这样,我看到缺少的主要内容是你已经剪掉的部分的累积器。当你到达你的位置时,你也不能退出,你必须记住你刚才剪掉的那一段,然后以同样的方式处理列表的其余部分。

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

2

我可能会做这种方式:

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我敢肯定,这可以更简洁的制作。

1
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 []