2016-01-20 94 views
1

list`扁平化'('名單* B名單)到'「列表*」 B list`我需要在OCaml的一個函數,將採取型 ('a list * b' list) list和利用它
'a list * b' list。我已經嘗試了內置函數List.flatten和List.concat,但它們不起作用,它們需要一個類型'c list list。有人能幫我嗎?功能在OCaml中

回答

1

您可以使用函數fold_left這樣做:

開始時你有兩個空表工作作爲蓄電池。對於輸入列表中的每個子列表,將元素添加到各自的累加器中(第一個累加器中的第一個子列表的元素和第二個子列表中的第一個子列表的元素)。

# let flatten l = 
    let (l1,l2) = 
    List.fold_left (fun (l1,l2) (x,y) -> 
     (x :: l1, y :: l2)) ([], []) l in 
    List.rev (List.flatten l1), List.rev (List.flatten l2);; 
     val flatten : ('a list * 'b list) list -> 'a list * 'b list = <fun> 
# 
+0

這是好的,但我需要的東西做 '(「名單*」 B名單)名單 - >'a list *'b list' and not '('a *'b)list - >'a list *'b list' – measuretheory

+0

我更新了答案:) – alifirat

+0

但它仍然不是我所需要的:(順序不是那麼重要,重要的是函數中的輸入是什麼,你給出'('a *'b)列表 - >'列表*'列表',我需要'('列表*'b列表)列表 - >'列表*'列表' – measuretheory

0

以下應該工作:

let split2 l = (List.map fst l, List.map snd l) 
let flatten2' (l1, l2) = (List.flatten l1, List.flatten l2) 
let flatten2 l = flatten2' (split2 l) 

這裏,split2會變成一個('a list * 'b list) list('a list list * 'b list list)fstsnd返回一個對所述第一和第二組分,分別地)和flatten2'將單獨弄平這兩個組件。而flatten2將最終做你所需要的。您也可以將其封裝到一個函數中,但我認爲這更容易理解。

請注意,List.mapList.flatten都不是尾遞歸;如果你需要尾遞歸版本,還有其他庫有它們,或者你可以使用rev_xxx函數從標準庫建立它們或者從頭開始編寫它們。

2

你要使用的功能List.splitList.flatten

let my_function l = 
    let (fst_list, snd_list) = List.split l in 
    List.flatten fst_list, List.flatten snd_list ;; 

首先split函數將生成和'a list list'b list list,那麼你只需要flatten他們。

1

不幸的是,沒有元組的映射,你需要分解 - 例如,通過採用分體式壓平:

let splcat x = match List.split x with | (a,b) -> (List.flatten a, List.flatten b) ;; 

這是它的外觀在命令行:

utop # splcat [([1;2],["a"]); ([3],["uvw";"xyz"]) ] ;; 
- : int list * bytes list = ([1; 2; 3], ["a"; "uvw"; "xyz"])