Erlang, replacing an atom with another one in a list
I want to write a function to replace a specific atom with the given atom in an input list. But I want to do it using pattern matching and not using conditional statements. Any idea?
And al开发者_开发百科so I want to write a function to return unique atoms in an expression. e.g.
Input:
[a, b, c, a, b]
Output:
c
Input:
[b, b, b, r, t, y, y]
Output:
[t, r]
Assuming you want to replace all instances and keep the order of the list (works with all terms):
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]).
For the unique elements filter, you need to keep a state of which elements you have looked at already.
It would be really awkward to implement such a function using only pattern matching in the function headers and you would not really gain anything (performance) from it. The awkwardness would come from having to loop through both the list in question and the list(s) keeping your state of already parsed elements. You would also loose a lot of readability.
I would recommend going for something simpler (works with all terms, not just atoms):
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)].
One way I'm looking for solving your first question would be to use guards, instead of if statements. Using only pattern matching doesn't seem possible (or desirable, even if you can do it).
So, for instance, you could do something like:
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).
EDIT: Edited for simplicity and style, thanks for the comments. :)
For the second part of your question, what do you consider an "expression"?
EDIT: Nevermind that, usort doesn't completely remove duplicates, sorry.
精彩评论