如何计算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