Erlang Thurday – ordsets:is_disjoint/2

今天的Erlang Thursday讲的是 ordsets:is_disjoint/2.

在日常的编码中,你应该会碰到这样的问题,如何判断一个给定的列表,它的元素不在另一个列表里出现。

你的第一个直觉可能写出的代码像如下这样:

1
2
not( lists:any(fun(Item) -> lists:member(Item, [1, 3, 5, 7]) end, [2, 4, 6])).
% true

如果你更多地在数学的范畴里定义你的问题,你可以从集合方向上开始思考,那么这个问题会更清晰。当你开始在集合的方向上思考,你会意识到你可以检查两个集合的交集是否是空集合。

1
2
ordsets:intersection([1, 3, 5, 7], [2, 4, 6]) =:= [].
% true

这样不仅更加简洁,而且更加明确你需要检查的是什么。

实际上,当你通过判断两个列表是否是不相交的,你可以做的更好。下面我们开始看看 ordsets:is_disjoint/2 。

ordsets:is_disjoint/2 接收两个列表做为入参,当两个列表没有共同的元素的时候函数返回true。

1
2
3
4
ordsets:is_disjoint([1, 3, 5, 7], [2, 4, 6]).
% true
ordsets:is_disjoint([1, 2, 3, 5, 7], [2, 4, 6]).
% false

因为 ordsets:is_disjoint/2 是对两个列表进行判断,所以我们没必要先调用所谓的 ordsets:disjoint/2 来确定列表元素是唯一的。

1
2
3
4
ordsets:is_disjoint([1, 1, 3, 5, 7, 5, 3], [2, 4, 2, 2, 6]).
% true
€ordsets:is_disjoint([1, 2, 3, 5, 7], [2, 4, 2, 2, 6]).
% false

如果任何一个入参是空列表,则 ordsets:is_disjoint/2 返回的结果都是说这两个列表是不相交的。

1
2
3
4
5
6
ordsets:is_disjoint([1, 2, 3, 5, 7], []).
% true
ordsets:is_disjoint([], [2, 4, 6]).
% true
ordsets:is_disjoint([], []).
% true

另外,如果你很好奇,想看看用 timer:tc/3 来测量 ordsets:is_disjoint/2 的运行时间,那么我们可以看到,只要 Erlang 知道了两个列表是不相交的,它就立马返回false,如果你记得我们前面的文章 Erlang Thursday on timer:tc/3 ,你就知道它的返回值是一个元组,元组的第一个元素就是代表被测量函数运行时间,其单位是微秒。

1
2
3
4
timer:tc(ordsets, is_disjoint, [lists:seq(1, 1000000), lists:seq(2000000, 3000000)]).
% {19032,true}
€timer:tc(ordsets, is_disjoint, [lists:seq(1, 1000000), lists:seq(1, 3000000)]).
% {2,false}

原文链接: https://www.proctor-it.com/erlang-thurday-ordsets-is_disjoint-2/