2011-02-28 19 views
1

作爲學習Erlang的練習,我試圖編寫一個簡單的數據庫(來自O'Reilly編程Erlang)。試圖在Erlang中列出問題的問題

基本上我有這樣的元組的列表:

Db1 = [{person1,charleston},{person2,charleston},{person3,chicago}]. 

我需要創建功能,使得

db:match(charleston,Db1). 

回報

[person1,person2] 

下面是我寫的方法:

match(Element, Db) -> match(Element, Db, []). 
match(_Element,[], Results) -> Results; 
match(Element, [{Key,Value}|T], Results) -> 
    case Value == Element of 
     true -> match(Element, T, [Results,Key]); 
     false -> match(Element,T,Results) 
    end. 

我找回結果是這樣的:

[[[],person1],person2] 

我知道有名單與lists.erl模塊相結合的方式,但我試圖繞過它在努力瞭解更多有關語言。任何想法我做錯了什麼?

+1

您的'案件值==元素'可以摺疊到子句中:match(Value,[{Key,Value} | T],...) - >'等等。 – 2011-02-28 13:37:11

+0

你的情況很簡單我不會在這裏使用尾遞歸累加器,而是使用'[Key | match(Element,T)]'作爲遞歸器。 – 2011-02-28 13:38:44

回答

5

問題是你如何建立你的清單,試試這個來代替:

case Value == Element of 
    true -> match(Element, T, [Key|Results]); 
    false -> match(Element,T,Results) 
end. 
  • [A,B]建立與元素一個新的列表和B.
  • [A | B ]將A前置到列表B中。
+0

這是原始代碼的問題。並且你交換了'Key'和'Results'。 – 2011-02-28 13:34:35

+0

爲什麼[密鑰|結果]不同於[結果|關鍵]。我認爲後半部分被附加到第一部分。沒有? – Micah 2011-02-28 14:19:46

+2

'Key'是一個值,而'Results'是一個值列表。 '[_ | _]'構造通常以'[Value | ListofValues]'的方式**將第一部分前置到第二部分。以相反的順序使用它是合法的,但它不是使用列表的正常方式,並且不支持此操作。將值附加到列表中是另一種效率低得多的操作,如果可能,通常會避免這種操作。 – rvirding 2011-02-28 14:24:32

7

您正在重新發明輪子。只需使用list comprehension

match(X, Db) -> [P || {P, E} <- Db, E == X]. 
+2

模式匹配更短:match(X,Db) - > [P || {P,X} < - Db]。 – hdima 2011-02-28 07:13:16

+2

@hdima該解決方案不起作用,因爲List Comprehensions生成器中的X會影響match/2參數X. – 2011-02-28 08:11:49

+0

我沒有把這個標記爲答案的唯一原因是我還沒有做過任何與模式匹配有關的事情,並且正在尋找特定的遞歸解決方案。但很好的答案。 – Micah 2011-03-02 16:33:23

1

的另一種方法寫的代碼是直接

match(_Value, []) -> []; 
match(Value, [{Key,Value}|T]) -> 
    [Key|match(Value, T)]; 
match(Value, [_|T]) -> 
    match(Value, T). 

列表理解在@Little鮑比表的解決方法是等效於此。

+0

它看起來不像你最後一次的比賽/ 3被稱爲。所有匹配的電話都是匹配/ 2。 – Micah 2011-02-28 18:11:02

+0

@Micah @Hynek糾正的錯字 – rvirding 2011-03-02 13:27:23