Reputation: 995
For Example:
Db = [{pid1, {key1, {apple}}}, {pid1, {key2, {banana}}}, {pid1, {key3, {watermelon}}}, {pid2, {key1, {cucumber}}}, {pid2, {key2, {carrot}}}].
Being able to return the tuple where Pid = pid1, and Key = key1, which would be {pid1, {key1, {apple}}}. How would I go about doing this? Something similar to the BIF lists:keyfind/3.
Upvotes: 1
Views: 177
Reputation: 6347
There are several ways to perform such lookups, and no best method. It is mostly a matter of style.
You can write a recursive function that will return as soon as the result is matched, as suggested by @Emil Vikström. The advantage is that you do not go through all the elements but the lookup will return as soon as a result is found, similar to what lists:keyfind/3
does. However, one could argue that if the list is long enough to justify such an optimization, another data structure could be more appropriate (like a sorted list or a tree).
You can use lists:filter/2
as suggested by @Pascal. This has the advantage over a recursive function to be based on a library function, which is always good for code maintenance.
You can use a filter within a list comprehension. This is similar than the lists:filter/2
approach, but a little shorter. Many see lists comprehension as more Erlang-like than using lists:map/2
and lists:filter/2
, especially when the test is so short.
[T || {Pid, {Key, _Value}} = T <- Db, Pid =:= MyPid, Key =:= MyKey].
If key1 and pid1 are constants, you can even write:
[T || {pid1, {key1, _Value}} = T <- Db].
Upvotes: 1
Reputation: 91983
If you want to break early when you find the value, you can implement it yourself using pattern matching:
pidkeyfind(_Pid, _Key, []) -> false;
pidkeyfind(Pid, Key, [Head = {Pid, {Key, _}} | _Tail]) -> Head;
pidkeyfind(Pid, Key, [_|Tail]) -> pidkeyfind(Pid, Key, Tail).
Upvotes: 0
Reputation: 14042
with lists:filter/2 it should work, here is an example of how to use it.
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}}}]
Upvotes: 1