2013-10-16 47 views
1

例如:找到一個元組與兩個鍵

Db = [{pid1, {key1, {apple}}}, {pid1, {key2, {banana}}}, {pid1, {key3, {watermelon}}}, {pid2, {key1, {cucumber}}}, {pid2, {key2, {carrot}}}]. 

如果能夠返回的元組其中pid = PID1和密鑰= key1的,這將是{PID1,{鍵,{蘋果}}}。我會如何去做這件事?類似於BIF列表:keyfind/3。

回答

0

如果你想,當你發現的價值,打破早,您也可以自己使用模式匹配實現它:

pidkeyfind(_Pid, _Key, []) -> false; 
pidkeyfind(Pid, Key, [Head = {Pid, {Key, _}} | _Tail]) -> Head; 
pidkeyfind(Pid, Key, [_|Tail]) -> pidkeyfind(Pid, Key, Tail). 
+0

這個作品,更說教,但假設有至多1個記錄中匹配請求,如果是這樣的話,它的平均速度應該更快。 – Pascal

+0

Pascal的確如此。我選擇了這種解釋(單擊),因爲這是list:keyfind/3的工作方式。 –

1

與列表:filter/2它應該工作,這裏是一個如何使用它的例子。

1> Db = [{pid1, {key1, {apple}}}, {pid1, {key2, {banana}}}, {pid1, {key3, {watermelon}}}, {pid2, {key1, {cucumber}}}, {pid2, {key2, {carrot}}}]. 
[{pid1,{key1,{apple}}}, 
{pid1,{key2,{banana}}}, 
{pid1,{key3,{watermelon}}}, 
{pid2,{key1,{cucumber}}}, 
{pid2,{key2,{carrot}}}] 
2> Find = fun (K1,K2,L) -> lists:filter(fun({X,{Y,_}}) -> X =:= K1 andalso Y =:= K2 end,L) end. 
#Fun<erl_eval.18.82930912> 
3> Find(pid1,key1,Db). 
[{pid1,{key1,{apple}}}] 
1

有幾種方法來進行這樣的查詢,並沒有最好的方法。這主要是,這與風格有關。

  • 你可以寫一個遞歸函數將由@Emil Vikström只要結果一致返回,因爲suggested。優點是你不會瀏覽所有元素,但只要找到結果,查找就會返回,類似於lists:keyfind/3所做的。然而,有人可能會爭辯說,如果列表足夠長以證明這樣的優化,另一個數據結構可能更合適(如排序列表或樹)。

  • 您可以使用lists:filter/2作爲suggested by @Pascal。這比基於庫函數的遞歸函數具有優勢,這對於代碼維護來說總是有利的。

  • 您可以使用列表理解內的過濾器。這與lists:filter/2方法相似,但稍短一些。許多人認爲列表理解比使用lists:map/2lists:filter/2更像Erlang,特別是當測試如此之短時。

    [T || {Pid, {Key, _Value}} = T <- Db, Pid =:= MyPid, Key =:= MyKey].

    如果key1的和PID1是常數,你甚至可以寫:

    [T || {pid1, {key1, _Value}} = T <- Db].