2011-04-29 109 views
1

我想編寫一個函數,用輸入列表中給定的原子替換特定的原子。但是我想用模式匹配來做,而不是使用條件語句。任何想法?Erlang,用列表中的另一個替換一個原子

而且我想寫一個函數來返回表達式中的獨特原子。 例如

輸入:

[a, b, c, a, b] 

輸出:

c 

輸入:

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

輸出:

[t, r] 
+2

這是相當不禮貌的問兩個完全不同的問題作爲一個問題。 – Dustin 2011-04-29 17:35:06

回答

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不會完全刪除重複,對不起。

+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

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)]. 
相關問題