【问题标题】:List reversing in Ocaml在 Ocaml 中反转列表
【发布时间】:2014-01-24 00:10:57
【问题描述】:

如果我们假设我们从 0 开始计数元素,如何反转列表的子列表。我希望解决方案是“手动编码”的。我对这个任务有很大的问题。

例如:

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;;

但现在我被困住了。

【问题讨论】:

    标签: ocaml


    【解决方案1】:
    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;;
    

    【讨论】:

    • 不过没关系,我也可以使用它。非常感谢!
    【解决方案2】:
    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
    

    注意它们都是尾递归的

    编辑

    给诺兰的建议:

    尾递归在函数式编程和 OCaml 中非常重要。请记住。

    【讨论】:

    • 除了mod,您可以使用相互递归函数跳过列表中的所有其他元素。
    • @nlucaroni 是的,你是对的。我这样写只是为了根据问题规范更直接地展示这个过程,考虑到诺兰是一个新的学习者。
    【解决方案3】:

    为了好玩,我做过这样的事情,

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

    【讨论】:

      猜你喜欢
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-14
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多