2012-11-07 46 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 []