2013-10-16 48 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].