【问题标题】:Finding a tuple with two keys查找具有两个键的元组
【发布时间】:2013-10-16 08:19:34
【问题描述】:

例如:

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。

【问题讨论】:

    标签: list erlang key tuples


    【解决方案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}}}]
    

    【讨论】:

      【解决方案2】:

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

      • 您可以编写一个递归函数,一旦匹配结果就会返回,如suggested by @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 &lt;- Db, Pid =:= MyPid, Key =:= MyKey].

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

        [T || {pid1, {key1, _Value}} = T &lt;- Db].

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 这行得通并且更具指导性,但它假设最多有 1 条记录与请求匹配,如果是这种情况,它应该平均更快。
        • 确实是帕斯卡。我选择了这种解释(单次点击),因为这就是 lists:keyfind/3 的工作原理。
        猜你喜欢
        • 1970-01-01
        • 2015-01-21
        • 1970-01-01
        • 2014-07-10
        • 2019-12-06
        • 1970-01-01
        • 2013-12-10
        • 2012-01-23
        • 2021-10-08
        相关资源
        最近更新 更多