所以我试图对这个整数列表进行排序,以便所有偶数都在前面,而赔率都在后面。我现在有我的程序,它在很大程度上起作用,但它一直在颠倒我不想要它做的赔率数字的顺序。例如。给出输入[1; 2; 3; 4; 5; 6]我想得到[2; 4; 6; 1; 3; 5],但我得到[2; 4; 6; 5] ; 3; 1]非常感谢任何帮助!
let rec evens (xl:int list) (odd:int list) : int list =
match xl with
| [] -> []
| h::t ->
if h mod 2 = 0
then (h)::evens t odd
else
evens t odd@[(h)]
答案 0 :(得分:2)
当前代码的主要部分解析如下:
if h mod 2 = 0 then
h :: (evens t odd)
else
(evens t odd) @ [h]
它说:如果下一个数字h
是偶数,请对列表的其余部分进行排序,然后将h
添加到前面。如果下一个数字h
为奇数,请对列表的其余部分进行排序,然后将h
添加到结尾。因此,奇数将在最后反转。
值得注意的是,名为odd
的参数始终保持不变,因此将始终为空列表(或者作为evens
的第二个参数传递的任何内容)。
当我第一次看到您的代码时,我假设您计划在odd
参数中累积奇数。如果您想这样做,则需要进行两项更改。首先你需要像这样重写:
if h mod 2 = 0 then
h :: evens t odd
else
evens t (odd @ [h])
如果要将h
添加到odd
参数,则OCaml的优先规则需要括号。您当前的代码会将h
添加到evens
的返回结果中(如上所述)。
此重写将在odd
参数中按顺序累积奇数。
然后你需要在递归结束时实际使用奇数参数。即,当xl
为空时,您需要使用它。
答案 1 :(得分:2)
标准库为您的问题提供了一个简洁的解决方案。
List.partition (fun x -> x mod 2 = 0) [1;2;3;4;5;6]
- : int list * int list = ([2; 4; 6], [1; 3; 5])
partition
函数将您的列表拆分为两个列表的元组:
您所要做的就是将这些列表组合在一起。
let even_first l =
let evens, odds = List.partition (fun x -> x mod 2 = 0) l in
evens @ odds
如果你想让它更通用,那么让谓词成为一个参数:
let order_by_predicate ~f l =
let valid, invalid = List.partition f l in
valid @ invalid