我正在尝试编写一个函数来检查集合(由列表表示)是否是另一个集合的子集。
我已经编写了一个辅助函数,它给了我交集:
let rec intersect_helper a b =
match a, b with
| [], _ -> []
| _, [] -> []
| ah :: at, bh :: bt ->
if ah > bh then
intersect_helper a bt
else if ah < bh then
intersect_helper at b
else
ah :: intersect_helper at bt
我正在尝试在子集函数中使用它(如果A是B的子集,那么A = A与B相交):
let subset a_ b_ =
let a = List.sort_uniq a_
and b = List.sort_uniq b_
in intersect_helper a b;;
错误:此表达式的类型为“列表 - &gt; '列表但是表达式需要'b list
类型
这到底出了什么问题?我可以自己完全使用intersect_helper
,但是在这里用列表调用它不起作用。根据我对'a
的了解,它只是第一个参数类型的占位符。列表也不应该是'a list
类型的颜色吗?
答案 0 :(得分:2)
我很高兴你能解决自己的问题,但你的代码对我来说似乎非常复杂。
如果我理解正确,你需要一个函数来告诉列表是否是另一个列表的子集。换句话说,您想知道列表a
中列表b
的所有元素是否都存在。
因此,你的函数的签名应该是
val subset : 'a list -> 'a list -> bool
标准库附带了各种操作列表的功能。
let subset l1 l2 =
List.for_all (fun x -> List.mem x l2) l1
List.for_all
检查列表中的所有元素是否满足给定条件。 List.mem
检查列表中是否存在值。
你有它。我们来看看结果:
# subset [1;2;3] [4;2;3;5;1];;
- : bool = true
# subset [1;2;6] [4;2;3;5;1];;
- : bool = false
# subset [1;1;1] [1;1];; (* Doesn't work with duplicates, though. *)
- : bool = true
备注:使用List.for_all
的一小部分优势在于它是short-circuit operator。这意味着只要项目不匹配就会停止,这样可以提高整体性能。
此外,由于您特别询问了集合,因此标准库为它们提供了一个模块。但是,集合使用起来有点复杂,因为它们需要您使用仿函数创建新模块。
module Int = struct
type t = int
let compare = Pervasives.compare
end
module IntSet = Set.Make(Int)
额外的开销是值得的,因为现在IntSet可以使用整个Set
接口,其中包括IntSet.subset
函数。
# IntSet.subset (IntSet.of_list [1;2;3]) (IntSet.subset [4;2;3;5;1]);;
- : bool = true
答案 1 :(得分:0)
而不是:
let a = List.sort_uniq a_
应该致电:
let a = List.sort_uniq compare a_