1

例如:

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。

4

3 回答 3

1

使用 lists: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}}}]
于 2013-10-16T08:44:49.650 回答
1

有几种方法可以执行此类查找,但没有最佳方法。这主要是风格问题

  • 正如@Emil Vikström所建议的那样,您可以编写一个递归函数,一旦结果匹配就会返回。优点是您不会遍历所有元素,但查找将在找到结果后立即返回,类似于执行的操作。但是,有人可能会争辩说,如果列表足够长以证明这种优化是合理的,那么另一种数据结构可能更合适(如排序列表或树)。lists:keyfind/3

  • 您可以lists:filter/2按照@Pascal 的建议使用。与基于库函数的递归函数相比,这具有优势,这总是有利于代码维护。

  • 您可以在列表理解中使用过滤器。这与lists:filter/2方法相似,但要短一些。lists:map/2许多人认为列表理解比使用and更像 Erlang lists:filter/2,尤其是在测试很短的时候。

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

    如果 key1 和 pid1 是常量,你甚至可以这样写:

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

于 2013-10-16T09:06:43.620 回答
0

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

pidkeyfind(_Pid, _Key, []) -> false;
pidkeyfind(Pid, Key, [Head = {Pid, {Key, _}} | _Tail]) -> Head;
pidkeyfind(Pid, Key, [_|Tail]) -> pidkeyfind(Pid, Key, Tail).
于 2013-10-16T08:48:09.360 回答