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

问题描述:

我想编写一个函数,用输入列表中给定的原子替换特定的原子。但是我想用模式匹配来做,而不是使用条件语句。任何想法?Erlang,用列表中的另一个替换一个原子

而且我想写一个函数来返回表达式中的独特原子。 例如

输入:

[a, b, c, a, b] 

输出:

c 

输入:

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

输出:

[t, r] 
+2

这是相当不礼貌的问两个完全不同的问题作为一个问题。 – Dustin 2011-04-29 17:35:06

我正在寻找解决您的第一个问题的一种方法是使用警卫,而不是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不会完全删除重复,对不起。

+1

你可以切换第一个和第二个子句,并删除“何时H/= To_replace” - 这很明显,如果==没有匹配,那么你不必更换该元素 – keymone 2011-04-29 12:10:14

+1

也不要混合命名约定 - To_replace是丑陋的,ToReplace是美丽的。 – keymone 2011-04-29 12:11:01

+0

是的,我对Erlang仍然很陌生,所以我仍然摸索一下。谢谢!编辑 – 2011-04-29 13:05:51

假设你要替换所有实例,并保持列表的顺序(所有条款适用):

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)].