Erlang,用列表中的另一个替换原子

时间:2011-04-29 10:55:53

标签: erlang

我想编写一个函数来用输入列表中的给定原子替换特定原子。但我想使用模式匹配而不是使用条件语句来实现。有什么想法吗?

我还想编写一个函数来返回表达式中的唯一原子。 e.g。

输入:

[a, b, c, a, b]   

输出:

c

输入:

[b, b, b, r, t, y, y]   

输出:

[t, r]

2 个答案:

答案 0 :(得分:1)

假设您要替换所有实例并保持列表的顺序(适用于所有术语):

replace(Old, New, List) -> replace(Old, New, List, []).

replace(_Old, _New, [],           Acc) -> lists:reverse(Acc);
replace(Old,  New,  [Old|List],   Acc) -> replace(Old, New, List, [New|Acc]);
replace(Old,  New,  [Other|List], Acc) -> replace(Old, New, List, [Other|Acc]).

对于唯一元素过滤器,您需要保持已查看的元素的状态。

在函数头中仅使用模式匹配来实现这样的函数真的很尴尬,你不会从中获得任何(性能)​​。尴尬来自于必须遍历所讨论的列表和保持已解析元素状态的列表。你也会失去很多可读性。

我建议选择更简单的东西(适用于所有术语,而不仅仅是原子):

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

unique([], Counts) ->
    lists:foldl(fun({E, 1}, Acc) -> [E|Acc];
                   (_,      Acc) -> Acc
                end, [], Counts);
unique([E|List], Counts) ->
    unique(List, count(E, Counts).

count(E, [])            -> [{E, 1}];
count(E, [{E, N}|Rest]) -> [{E, N + 1}|Rest];
count(E, [{X, N}|Rest]) -> [{X, N}|count(E, Rest)].

答案 1 :(得分:0)

我正在寻找解决你的第一个问题的一种方法是使用警卫而不是if语句。仅使用模式匹配似乎不可能(或者即使您可以这样做也是可取的)。

因此,例如,您可以执行以下操作:

my_replace([H|T], ToReplace, Replacement, Accum) when H == ToReplace ->
    my_replace(T, ToReplace, Replacement, [Replacement|Accum]);

my_replace([H|T], ToReplace, Replacement, Accum) ->
    my_replace(T, ToReplace, Replacement, [H|Accum]);

my_replace([], ToReplace, Replacement, Accum) ->
    lists:reverse(Accum).

编辑:为了简单和风格而编辑,感谢您的评论。 :)

对于你问题的第二部分,你认为什么是“表达”?

编辑:没关系,usort并没有完全删除重复项,抱歉。