所以我想要交叉两个排序列表,这样intersect ([1;1;1;2;2], [1;1;2;4])
将返回[1;1;2]
。我走到这一步:
let rec intersect (xs, xs') =
match xs, xs' with
| ([], []) -> []
| (x::tail, []) -> []
| ([], x'::tail') -> []
| (x::tail, x'::tail') -> if x = x' then x::intersect(tail, tail')
else intersect(tail, xs')
但我不太确定从哪里开始。该函数采用包含两个列表的元组,我假设当每个列表的头部彼此相等时,我开始建立一个新列表,但我遗漏了一些我无法弄清楚的东西,并希望得到一个提示。
编辑:我知道我可以使用库函数来轻松解决这个问题,但这并不好玩:)
答案 0 :(得分:4)
以下是我提出的建议:
let rec intersect xs ys =
match xs, ys with
| x::xs', y::ys' ->
if x = y then x :: intersect xs' ys'
elif x < y then intersect xs' ys
else intersect xs ys'
| _ -> []
我删除了参数的元组,因为我没有理由这样做。
x::xs'
只会与非空列表匹配,因此基本案例匹配可以移到最后并简化为_
。
我也更改了名字。我发现最好只在引用已存在值的下一次迭代的名称中使用tick后缀。在这种情况下,您有一个列表xs
,其尾部为xs'
。
答案 1 :(得分:2)
我建议您将参数重命名为l1
和l2
,并与(x :: xs)
和(y :: ys)
匹配,即
let rec intersect (l1, l2) =
match l1,l2 with
...
| (x :: xs), (y :: ys) when x < y ->
你遗漏的两个案例是两个头不同的地方,即x < y
或x > y
。如果x < y
,那么由于列表已排序,l2
前面有一个或多个元素可以忽略,因为它们不能存在于l1
中,例如x = 5
。如果
l2 = [1;2;4;5]
和[1;2;4]
然后//removes items from the front of l which cannot occur in a sorted list with head e
let rec skipUntil e l = ...
可以被丢弃以找到下一场比赛。
我建议你写一个实用函数,它会丢弃一个无法找到的列表前面的元素,例如。
x > y
删除这些元素后,您可以继续搜索。
对称处理nmcli c | cat -vet
的情况。