2014-01-22 89 views
1

如果我們假設從0計數元素,如何反轉列表的子列表。我希望解決方案是「手動編碼」的。這個任務我遇到了很大的問題。Ocaml中的列表反轉

例如:

Function([[1;2;3] ; [2;3] ; [1;2;3] ; [5;6;7]]) 

回報:

([[3;2;1] ; [2;3] ; [3;2;1] ; [5;6;7]]) 

我已經創建了一個反向單列表的功能:

let rev = 
    let rec rev_append acc l = 
    match l with 
     [] -> acc 
    | h::t -> rev_append (h::acc) t in 
    fun l -> rev_append [] l;; 

但現在我卡住了。

回答

1
let rev_list l = 
    let rec rev_acc acc = function 
    | [] -> acc 
    | hd::tl -> rev_acc (hd::acc) tl 
    in 
    rev_acc [] l 

let rev_even l = 
    let rec rev i acc = function 
    | [] -> rev_list acc 
    | hd::tl -> 
     if i mod 2 = 0 then rev (i+1) ((rev_list hd)::acc) tl 
     else rev (i+1) (hd::acc) tl 
    in 
    rev 0 [] l 

注意,他們都是尾遞歸

編輯

有人建議的Noran:

尾遞歸是函數式編程和OCaml中非常重要。請記住。

+0

可以使用相互遞歸函數來跳過列表中的其他每個元素,而不是使用'mod'。 – nlucaroni

+1

@nlucaroni是的,你是對的。考慮到Noran是一個新的學習者,我寫這種方式只是爲了根據問題規範更直接地展示過程。 –

+0

是的,非常感謝。 Greate工作:) –

3
let rec todo l = let rec aux r = function 
     | [] -> [] 
     | h::t -> (if r then h else rev h)::(aux (not r) t) 
in aux true l;; 
+0

它不工作的罰款。它反向列表1,3,5 ...而不是0,2,4 ... –

+0

但是沒關係,我也可以利用它。非常感謝! –

1

爲了好玩,我已經做了這樣的東西,

let rev_at_even_idx list = 
    let s0, s1 = ([], 0), [] in 
    let aux0 (a, i) x = 
    (x, i mod 2) :: a, succ i 
    in 
    let aux1 a = function 
    | l, 0 -> List.rev l :: a 
    | l, _ -> l :: a 
    in 
    List.fold_left aux1 s1 
    @@ fst @@ 
    List.fold_left aux0 s0 list 
;; 

rev_at_even_idx [[1;2;3] ; [2;3] ; [1;2;3] ; [5;6;7]];; 
- : int list list = [[3; 2; 1]; [2; 3]; [3; 2; 1]; [5; 6; 7]]