OCaml - 将列表分成两个单独的,大于或小于给定的数字

时间:2014-10-21 10:29:18

标签: list ocaml

我在编写函数时遇到问题,结果如下所示:

split([7;1;4;3;6;8;2], 4) = ([1;3;2;4], [7;6;8])

我目前编写的代码:

let split(list, number)=
  let split1(list, number, lesser, greater)=
    if list = [] then lesser::greater
    else if List.hd list <= element then (List.hd list)::(lesser)
    else (List.hd list)::(greater)
  in 
  (List.tl lista, element, [], []);;

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

也许我对以下代码段的评论会有所帮助:

let split list num = 
  let rec loop lesser greater list =
    match list with
    | [] -> (lesser, greater)
    (* when your initial list is empty, you have to return the accumulators *)
    | x :: xs ->      
      if x <= num then 
          (* x is lesser than num, so add x in the lesser list and
             call loop on the tail of the list (xs)  *) 
      else 
          (* x is greater than num, so add x in the greater list and
             call loop on the tail of the list (xs)  *)  
  in
  (* here you make the first call to loop  by initializing 
     your accumulators with empty list*)
  loop [] [] list 

答案 1 :(得分:0)

对于未来,在SO上提问时更有针对性。你的问题究竟是什么?如果有人希望别人帮助他们,那么用户会持怀疑态度,但他们不会自助。

您的代码几乎具有正确的结构,但是有一些错误似乎正在妨碍您。

首先lesser::greater是错误的,因为cons运算符的左侧必须是一个列表本身,但你真正想要的是一个列表,其中这两个都是元素。所以请尝试[lesser;greater]

其次,如果你仔细考虑你的代码,你会发现它突然停止了。您检查了第一个元素,但是您没有查看列表的其余部分。由于您希望继续拆分列表,因此您需要使用代码继续执行直到列表末尾。为此,我们使用递归。递归意味着您的函数split1将再次调用自身。第一次看到它时可能会非常混乱 - 每次split1运行时,它将关闭第一个元素,然后拆分列表的其余部分

(List.hd list)::(lesser)实际上意味着什么?这里的较小部分实际上意味着列表其余部分中的所有较小元素 。你需要继续从列表中取出一个元素并将其放入更小或更大的位置。

最后避免过度使用List.hd - 使用模式匹配找到头部和尾部更为简洁。

这是代码的工作版本:

let split(list, number)=
  let rec split1(list, number, lesser, greater)=
    match list with
    | [] -> [List.rev lesser;List.rev greater]
    | head::tail ->
      match (head <= number) with
        true  -> split1(tail,number,head::lesser,greater)
      | false -> split1(tail,number,lesser,head::greater)
  in split1(list, number, [], []);;

split([1;2;3;4;5],3);;

split1函数一次关闭一个元素,并将它们添加到列表中。