我有一个将list2追加到list1的自定义函数。
let append ls1 ls2 =
let rec loop ls ls1 ls2 =
match ls1, ls2 with
| _, hd::tl ->
loop (hd::ls) ls1 tl
| hd::tl, _ -> loop (hd::ls) tl ls2
| _ -> ls
loop [] ls1 ls2
工作正常。但问题是当我调用函数
时let appended = append [1;2;3;4;5] [6;7;8;9;10]
而不是返回[1;2;3;4;5;6;7;8;9;10]
,它返回
[5;4;3;2;1;10;9;8;7;6]
它反转了两个列表。
答案 0 :(得分:2)
以下代码为我制定了
let rec append list1 list2 =
match list1, list2 with
| hd::tl, _ -> hd::(append tl list2)
| _, hd::tl -> hd::(append list1 tl)
| _ -> []
以下代码的输出为:
let List1 = [1; 3; 5];
let List2 = [7]
printf "%A" append List1 List2
是
[1; 3; 5; 7]
答案 1 :(得分:1)
您需要撤消列表。
解决方案的一种方法是考虑rev
函数的外观。
这是第一次尝试:
let rec rev lst =
match lst with
| h::t -> (rev t)@[h]
| [] -> []
这个函数反转一个列表,但是现在让我们做另一个使用累加器的版本,这意味着我们将使用另一个参数来代替在最后一行使用空列表:
let rec rev lst acc =
match lst with
| h::t -> rev t (h::acc)
| [] -> acc
所以现在我们必须将空列表作为参数传递:
rev [1..4] [];;
val it:int list = [4; 3; 2; 1]
您可能想知道为什么我们需要这样的功能,这个功能是tail recursive但是这不是您的问题,您希望附加两个列表。事实证明,这是您正在寻找的功能的90%。
如果不是传递空列表,而是传递第二个列表:
rev [1..4] [5..8];;
val it:int list = [4; 3; 2; 1; 5; 6; 7; 8]
很接近,但是,是的,第一个列表是颠倒的,好的,但我们有这个功能可以反转列表,所以让我们颠倒第一个列表:
rev (rev [1..4] []) [5..8] ;;
val it:int list = [1; 2; 3; 4; 5; 6; 7; 8]
很好,现在这个rev
可以是我们的loop
功能:
let append lst1 lst2 =
let rec rev lst acc =
match lst with
| h::t -> rev t (h::acc)
| [] -> acc
rev (rev lst1 []) lst2
哪个按预期工作,但请注意我们只是调用两次参数化rev
函数。希望您了解函数式编程如何允许您组合函数以解决不同的问题。在这种情况下,我们将一个函数与自身结合起来。