用两把钥匙找到一个元组

时间:2013-10-16 08:19:35

标签: list erlang key tuples

例如:

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

能够返回Pid = pid1和Key = key1的元组,即{pid1,{key1,{apple}}}。我该怎么做呢?类似于BIF列表的东西:keyfind / 3.

3 个答案:

答案 0 :(得分:1)

带有list: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 :(得分:1)

有几种方法可以执行此类查找,而且没有最佳方法。它主要是的风格

  • 您可以编写一个递归函数,它会在结果匹配后立即返回,suggested@Emil Vikström。优点是您不会遍历所有元素,但查找将在找到结果时立即返回,类似于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].

答案 2 :(得分:0)

如果您想在找到值时提前中断,可以使用模式匹配自行实现:

pidkeyfind(_Pid, _Key, []) -> false;
pidkeyfind(Pid, Key, [Head = {Pid, {Key, _}} | _Tail]) -> Head;
pidkeyfind(Pid, Key, [_|Tail]) -> pidkeyfind(Pid, Key, Tail).
相关问题