本文包括了erlang文档中所有的lists函数,每个函数可能包括如下几部分内容:
- 源码 (注:对于sort,merge等与排序有关的函数代码并不完整)
- 作用 (对函数作用做简单说明)
- 参数限制 (对函数参数或返回值进行说明)
- 代码解析 (个人对代码的一些解读)
- 疑惑 (对源码的一些疑惑)
- 思考 (对源码的一些思考)
函数目录:
-
-
- lists:all/2
- lists:any/2
- lists:append/1
- lists:subtract/2
- lists:reverse/2
- lists:reverse/1
- lists:nth/2
- lists:nthtail/2
- lists:prefix/2
- lists:suffix/2
- lists:droplast/1
- lists:last/1
- lists:seq/2
- lists:seq/3
- lists:merge/1
- lists:merge/2
- lists:merge/3
- lists:merge3/3
- lists:concat/1
- lists:flatten/1
- lists:flatten/2
- lists:flatlength/1
- lists:sum/1
- lists:duplicate/2
- lists:min/1
- lists:max/1
- lists:sublist/2
- lists:sublist/3
- lists:delete/2
- lists:zip/2
- lists:unzip/1
- lists:zip3/3
- lists:unzip3/3
- lists:zipwith/3
- lists:zipwith3/4
- lists:sort/1
- lists:keydelete/3
- lists:keyreplace/4
- lists:keytake/3
- lists:keystore/4
- lists:keysort/2
- lists:ukeysort/2
- lists:keymerge/3
- lists:ukeymerge/3
- lists:keymap/3
- lists:sort/2
- lists:usort/2
- lists:merge/3
- lists:umerge/3
- lists:usort/1
- lists:umerge/1
- lists:umerge/2
- lists:umerge3/3
- lists:map/2
- lists:flatmap/2
- lists:foldl/3
- lists:foldr/3
- lists:filter/2
- lists:partition/2
- lists:filtermap/2
- lists:zf/2
- lists:foreach/2
- lists:mapfoldl/2
- lists:mapfoldr/2
- lists:takewhile/2
- lists:dropwhile/2
- lists:splitwith/2
- lists:split/2
- lists:join/2
-
lists:all/2
源码:
-spec all(Pred, List) -> boolean() when
Pred :: fun((Elem :: T) -> boolean()),
List :: [T],
T :: term().
all(Pred, [Hd|Tail]) ->
case Pred(Hd) of
true -> all(Pred, Tail);
false -> false
end
作用:
- 传入一个函数Pred和列表List,对列表中每个元素执行函数Pred,如果所有都返回true,则怎个函数返回true,否则有一个返回false,就返回false。
参数限制:
- 函数参数是有且仅有一个任意erlang数据结构。
返回值必须是boolean()类型。
lists:any/2
源码:
-spec any(Pred, List) -> boolean() when
Pred :: fun((Elem :: T) -> boolean()),
List :: [T],
T :: term().
any(Pred, [Hd|Tail]) ->
case Pred(Hd) of
true -> true;
false -> any(Pred, Tail)
end;
any(Pred, []) when is_function(Pred, 1) -> false.
作用:
- 和lists:all/2 的不同可以从代码看出,lists:any/2 是只要有一个为true,那么函数就返回true,否则返回false。
参数限制(和lists:all/2 的类型规范相同):
- 函数参数是有且仅有一个任意erlang数据结构。
- 返回值必须是boolean()类型。
lists:append/1
源码:
-spec append(ListOfLists) -> List1 when
ListOfLists :: [List],
List :: [T],
List1 :: [T],
T :: term().
append([E]) -> E; % 这句的作用?为什么在第一行?
append([H|T]) -> H ++ append(T);
append([]) -> [].
作用:
- 将ListOfList 整合为一个列表,也就是如果是类似: [ [1,2],[2,4,5]] 返回为 [ 1,2,2,4,5]。
参数限制:
- ListOfLists是一个列表,列表的第二级必须是列表,第三级可以是任意erlang数据类型。
lists:subtract/2
源码:
-spec subtract(List1, List2) -> List3 when
List1 :: [T],
List2 :: [T],
List3 :: [T],
T :: term().
subtract(L1, L2) -> L1 -- L2.
作用:
- 去除掉List1中所有的List2元素。这里使用的-- ,则需要注意,如果List1中有3个a元素,List2中有2个a元素,那么结果只是去除List1中的2个a元素。(可以去搜索–符号的定义。)
参数限制:
- 参数是一个列表,列表的每个元素可以是任意erlang数据类型。
lists:reverse/2
源码:
-spec reverse(List1, Tail) -> List2 when
List1 :: [T],
Tail :: term(),
List2 :: [T],
T :: term().
reverse(_, _) ->
erlang:nif_error(undef).
疑惑:
- 这个函数的 erlang:nif_error(undef).没有看懂。reverse/1 第四个子句会调用这个函数是什么目的?
lists:reverse/1
源码:
-spec reverse(List1) -> List2 when
List1 :: [T],
List2 :: [T],
T :: term().
reverse([] = L) ->
L;
reverse([_] = L) ->
L;
reverse([A, B]) ->
[B, A];
reverse([A, B | L]) ->
lists:reverse(L, [B, A]).
作用:
- 反转List1中元素。
代码解析:
- 前三个子句针对列表只有0个或1个或2个的情况。如果列表元素超过3个,则匹配第三个子句。
lists:nth/2
源码:
-spec nth(N, List) -> Elem when
N :: pos_integer(),
List :: [T,...],
Elem :: T,
T :: term().
nth(1, [H|_]) -> H;
nth(N, [_|T]) when N > 1 ->
nth(N - 1, T).
作用:
- 获得列表中的第N个元素。
代码解析:
- 如果N为1,那么直接返回列表第1个元素;如果N大于1,那么就一直匹配第2个子句,直到N=1,且列表为排除前N-1个元素的列表,这时第1个元素就是原列表的第N个元素。
lists:nthtail/2
源码:
-spec nthtail(N, List) -> Tail when
N :: non_neg_integer(),
List :: [T,...],
Tail :: [T],
T :: term().
nthtail(1, [_|T]) -> T;
nthtail(N, [_|T]) when N > 1 ->
nthtail(N - 1, T);
nthtail(0, L) when is_list(L) -> L.
作用:
- 返回列表中第N+1 到结尾的列表。
代码解析:
- 第1-2个子句作用和nth/1函数相同,直到匹配到N为1,列表为N到结尾。最后一个是匹配当N为0时,判断L是否为列表。
思考:
- 如果第3个子句没有 when is_list(L) ,那么是否可以写成:
nthtail(0, L) -> L;
nthtail(N, [_|T]) when N >0 ->
nthtail(N - 1, T);
问题在于,when is_list(L) 意义何在?
lists:prefix/2
源码:
-spec prefix(List1, List2) -> boolean() when
List1 :: [T],
List2 :: [T],
T :: term().
prefix([X|PreTail], [X|Tail]) ->
prefix(PreTail, Tail);
prefix([], List) when is_list(List) -> true;
prefix([_|_], List) when is_list(List) -> false.
作用:
- 判断List1是否是List2的前缀,是返回true,否则返回false。
代码解析:
- 第1个子句明显是做等值匹配,第2-3个子句判断,如果匹配了所有相等元素之后List2是否为空,如果是则返回true,否则返回false。
lists:suffix/2
源码:
-spec suffix(List1, List2) -> boolean() when
List1 :: [T],
List2 :: [T],
T :: term().
suffix(Suffix, List) ->
Delta = length(List) - length(Suffix),
Delta >= 0 andalso nthtail(Delta, List) =:= Suffix.
作用:
- 判断List1是否是List2的后缀,是返回true,否则返回false。
代码解析:
- 首先判断List2长度是否大于List1,如果大于则继续判断,nthtail/2函数,获得List2的最后Delta个元素,与Suffix进行完全等值匹配。如果两个判断都为true,返回true,否则返回false。
思考:
- 为什么前缀判断不这样先判断长度,然后直接截取与带判断相同的前缀列表,再做完全等值判断呢?
这可能是因为,要截取出前缀同样需要函数递归寻找,而suffix,调用的nthtail也是做了递归寻找工作,因此不需要再自己写代码了,直接使用就可。
lists:droplast/1
源码:
-spec droplast(List) -> InitList when
List :: [T, ...],
InitList :: [T],
T :: term().
droplast([_T]) -> [];
droplast([H|T]) -> [H|droplast(T)].
作用:
- 删除列表最后一个元素。
参数限制:
- 从类型规范中可以看出List必须有一个元素,也就是不能为空,否则报错。
代码解析:
- 第1个子句匹配时已经是最后一个元素,直接忽略,返回空列表;第2个子句做递归,直到最后一个元素。
lists:last/1
源码:
-spec last(List) -> Last when
List :: [T,...],
Last :: T,
T :: term().
last([E|Es]) -> last(E, Es).
last(_, [E|Es]) -> last(E, Es);
last(E, []) -> E.
作用:
- 返回最后一个元素。
参数限制:
- 列表不能为空
代码解析:
- 主题为last/2 函数,它第1个子句递归调用,直到尾列表为空,则返回。
lists:seq/2
源码:
-spec seq(From, To) -> Seq when
From :: integer(),
To :: integer(),
Seq :: [integer()].
seq(First, Last)
when is_integer(First), is_integer(Last), First-1 =< Last ->
seq_loop(Last-First+1, Last, []).
seq_loop(N, X, L) when N >= 4 ->
seq_loop(N-4, X-4, [X-3,X-2,X-1,X|L]);
seq_loop(N, X, L) when N >= 2 ->
seq_loop(N-2, X-2, [X-1,X|L]);
seq_loop(1, X, L) ->
[X|L];
seq_loop(0, _, L) ->
L.
作用:
- 返回First到Last的列表。当First=Last返回First值,如果First=Last +1返回空列表。
参数限制:
- First <= Last+1。
代码解析:
- 函数分两部分,主体为seq_loop/3,利用第三个参数叠加值并返回。
第一参数是列表的大小,也就是要创建多少个元素。函数从最后一个元素开始创建,这样最后的列表顺序才正确。
函数妙的地方在于seq_loop/3的第1-2个子句,它们会对列表匹配做4个或2个的跳跃。利用[ X-3,X-2,X-1,X|L] 来直接创建4个或2个待入列元素。
lists:seq/3
源码:
-spec seq(From, To, Incr) -> Seq when
From :: integer(),
To :: integer(),
Incr :: integer(),
Seq :: [integer()].
seq(First, Last, Inc)
when is_integer(First), is_integer(Last), is_integer(Inc) ->
if
Inc > 0, First - Inc =< Last;
Inc < 0, First - Inc >= Last ->
N = (Last - First + Inc) div Inc, % 计算有多少个数
seq_loop(N, Inc*(N-1)+First, Inc, []);
Inc =:= 0, First =:= Last ->
seq_loop(1, First, Inc, [])
end.
seq_loop(N, X, D, L) when N >= 4 ->
Y = X-D, Z = Y-D, W = Z-D,
seq_loop(N-4, W-D, D, [W,Z,Y,X|L]);
seq_loop(N, X, D, L) when N >= 2 ->
Y = X-D,
seq_loop(N-2, Y-D, D, [Y,X|L]);
seq_loop(1, X, _, L) ->
[X|L];
seq_loop(0, _, _, L) ->
L.
作用:
- 返回First到Last范围内,以Incr为等差值的列表。
代码解析:
- seq/3的代码和seq/2差不多,不同之处在于多了一个等差值D,可以注意到seq_loop的第一个子句没有使用如Y=X-3D,Z=X-2D之类的代码是为了提高效率,因为加法比乘法快。
lists:merge/1
源码:
-spec merge(ListOfLists) -> List1 when
ListOfLists :: [List],
List :: [T],
List1 :: [T],
T :: term().
merge(L) ->
mergel(L, []).
作用:
- 将ListOfLists中的列表合并,如果想要合并之后有序,那么每个子列表需要自行先排序。否则无法保证返回列表有序。
参数限制:
- ListOfLists的子元素必须是列表。
lists:merge/2
源码:
-spec merge(List1, List2) -> List3 when
List1 :: [X],
List2 :: [Y],
List3 :: [(X | Y)],
X :: term(<