如何计算erlang中列表内容的长度?
How to count the length of the content of a list in erlang?
例如:["hello","world wide","1","2","3"]
长度为 18,包括 world 和 wide 之间的 space。
我试过:
string:len(lists:flatten([X|Y]))
但它删除了 spaces.
我想用它来做什么:
我正在创建一个函数,它将 return 尽可能多的单词列表,但保持在指定长度以下。
示例:
-spec hello(list(string()), integer()) -> list(string()).
1> hello:limit_word(["Hello", "there my friend", "wassup!"],10).
["Hello"]
2> hello:limit_word(["Hello", "there my friend", "wassup!"],22).
["Hello", "there my friend"]
展平并计算总长度的效果很好:
1> L = ["hello","world wide","1","2","3"].
["hello","world wide","1","2","3"]
2> string:length(lists:flatten(L)).
18
您也可以将每个部分的长度相加:
3> lists:sum([length(S) || S <- L ]).
18
或者您可以像这样实现 limit_word
函数:
-module(hello).
-export([limit_word/2]).
limit_word(L, Max) ->
limit_word(L, Max, {0, []}).
limit_word([H|T], Max, {Size, Acc}) ->
NewSize = Size + length(H),
case NewSize > Max of
false ->
limit_word(T, Max, {NewSize, [H|Acc]});
true->
lists:reverse(Acc)
end;
limit_word([], _, {_, Acc}) ->
lists:reverse(Acc).
limit_word/2
是导出给调用者的内容(与您的原始示例相同)。它只是调用 limit_word/3
函数,该函数接受一个额外的参数:当前总长度 Size
和累积单词 Acc
的元组。我们取列表的头部,将其长度添加到 Size
,如果总数小于 Max
,我们递归调用 limit_word/3
,传递 NewSize
和一个新列表以新词为首、现有词表为尾的词组。但是如果 NewSize
超过 Max
,我们 return 反转的 Acc
列表——反转是因为我们通过向头部添加新词来形成列表。正如您所期望的那样工作:
4> hello:limit_word(["Hello", "there my friend", "wassup!"],10).
["Hello"]
5> hello:limit_word(["Hello", "there my friend", "wassup!"],22).
["Hello","there my friend"]
更新:如果所有列表元素的总长度小于 Max
,我们永远不会遇到 true
情况,因此最后的 limit_word/3
子句通过以下方式处理空输入列表return反转累加器。
您可以使用 iolist_size/1
:
> iolist_size(["hello","world wide","1","2","3"]).
18
例如:["hello","world wide","1","2","3"]
长度为 18,包括 world 和 wide 之间的 space。
我试过:
string:len(lists:flatten([X|Y]))
但它删除了 spaces.
我想用它来做什么: 我正在创建一个函数,它将 return 尽可能多的单词列表,但保持在指定长度以下。
示例:
-spec hello(list(string()), integer()) -> list(string()).
1> hello:limit_word(["Hello", "there my friend", "wassup!"],10).
["Hello"]
2> hello:limit_word(["Hello", "there my friend", "wassup!"],22).
["Hello", "there my friend"]
展平并计算总长度的效果很好:
1> L = ["hello","world wide","1","2","3"].
["hello","world wide","1","2","3"]
2> string:length(lists:flatten(L)).
18
您也可以将每个部分的长度相加:
3> lists:sum([length(S) || S <- L ]).
18
或者您可以像这样实现 limit_word
函数:
-module(hello).
-export([limit_word/2]).
limit_word(L, Max) ->
limit_word(L, Max, {0, []}).
limit_word([H|T], Max, {Size, Acc}) ->
NewSize = Size + length(H),
case NewSize > Max of
false ->
limit_word(T, Max, {NewSize, [H|Acc]});
true->
lists:reverse(Acc)
end;
limit_word([], _, {_, Acc}) ->
lists:reverse(Acc).
limit_word/2
是导出给调用者的内容(与您的原始示例相同)。它只是调用 limit_word/3
函数,该函数接受一个额外的参数:当前总长度 Size
和累积单词 Acc
的元组。我们取列表的头部,将其长度添加到 Size
,如果总数小于 Max
,我们递归调用 limit_word/3
,传递 NewSize
和一个新列表以新词为首、现有词表为尾的词组。但是如果 NewSize
超过 Max
,我们 return 反转的 Acc
列表——反转是因为我们通过向头部添加新词来形成列表。正如您所期望的那样工作:
4> hello:limit_word(["Hello", "there my friend", "wassup!"],10).
["Hello"]
5> hello:limit_word(["Hello", "there my friend", "wassup!"],22).
["Hello","there my friend"]
更新:如果所有列表元素的总长度小于 Max
,我们永远不会遇到 true
情况,因此最后的 limit_word/3
子句通过以下方式处理空输入列表return反转累加器。
您可以使用 iolist_size/1
:
> iolist_size(["hello","world wide","1","2","3"]).
18