如何将List转换为元组的列表?

3
我想将[z,z,a,z,z,a,a,z]转换为[{z,2},{a,1},{z,2},{a,2},{z,1}]。我该如何做?
所以,我需要累积先前的值、计数和元组列表。
我已经创建了记录。
-record(acc, {previous, counter, tuples}).

重新定义
listToTuples([]) -> [];
listToTuples([H | Tail]) -> 
    Acc = #acc{previous=H, counter=1},
    listToTuples([Tail], Acc).

但是我遇到了一些麻烦

listToTuples([H | Tail], Acc) ->   
    case H == Acc#acc.previous of
        true  ->
        false ->
    end.
3个回答

9

如果您以相反的顺序构建答案(Acc),则前一个将成为该列表的头部。

以下是我的做法--

list_pairs(List) -> list_pairs(List, []).

list_pairs([], Acc) -> lists:reverse(Acc);
list_pairs([H|T], [{H, Count}|Acc]) -> list_pairs(T, [{H, Count+1}|Acc]);
list_pairs([H|T], Acc) -> list_pairs(T, [{H, 1}|Acc]).
(我预计现在会有人跟进一个一行的列表推导版本...)

我怀疑你能用列表推导完成这个任务。你至少需要使用折叠函数。 - I GIVE CRAP ANSWERS

6
我将继续在反向构建列表的道路上前进。请注意第一行中对X进行的模式匹配。
F = fun(X,[{X,N}|Rest]) -> [{X,N+1}|Rest];
       (X,Rest)         -> [{X,1}|Rest] end.

lists:foldr(F,[],List).

1
使用 lists:foldr/3,你就完成了。 ;) - D.Nibon
使用lists:foldr/3函数时,并不是以相同的方式构建列表的逆序,至少不像在累加器上调用lists:reverse/1那样。lists:foldr函数只是从右到左处理列表,因此它按照逆序处理所有元素,这是其定义的行为。尽管它不是尾递归的,但这并不总是坏事。文档中已经提到了这一点。 - rvirding

3

我个人会使用lists:foldr/3或手动完成,例如:

list_to_tuples([H|T]) -> list_to_tuples(T, H, 1);
list_to_tuples([]) -> [].

list_to_tuples([H|T], H, C) -> list_to_tuples(T, H, C+1);
list_to_tuples([H|T], P, C) -> [{P,C}|list_to_tuples(T, H, 1);
list_to_tuples([], P, C) -> [{P,C}].

使用两个累加器可以避免在列表中的每个元素上不必要地构建和拆分元组。我发现以这种方式编写更清晰。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接