【问题标题】:Erlang: Delete a map in a list of maps, then return the listErlang:删除地图列表中的地图,然后返回列表
【发布时间】:2016-02-17 05:39:46
【问题描述】:

我目前在我的程序的服务器端工作,我正在寻找一种方法来在我发现某个映射具有我正在搜索的原子后立即消除它。

下面的代码可以成功找到带有原子的映射是否存在于映射列表中,但我正在寻找一种方法从列表中删除该映射并返回整个列表而不返回我刚刚删除的映射。

“Asistente”是我正在寻找的原子。 L_Asistente 是地图本身的列表

第一种方法是当您覆盖整个列表但在地图列表中找不到原子时。

第二个是搜索本身。目前,它会在找到目标时返回 true,但我想将其更改为整个列表减去包含我正在搜索的原子的地图。

server_checaExistenciaBorrarAsistente(_, []) ->
    false;

server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
    [MapAsistente | Rest] = L_Asistentes,
    io:format("~p == ~p ~n", [MapAsistente, Asistente]),
    case maps:get("clave",MapAsistente) == Asistente of
        true ->
            true;
        false -> 
            server_checaExistenciaAsistente(Asistente, Rest)
    end. 

【问题讨论】:

    标签: list erlang maps


    【解决方案1】:

    这里需要用到累加器:

    server_checaExistenciaBorrarAsistente(_, [], Acc) ->
        Acc;
    
    server_checaExistenciaBorrarAsistente(Asistente, [MapAsistente | Rest], Acc) ->
        io:format("~p == ~p ~n", [MapAsistente, Asistente]),
        case maps:find("clave", MapAsistente) of
            {ok, _} ->
                server_checaExistenciaBorrarAsistente(Asistente, Rest, Acc);
            error -> 
                server_checaExistenciaBorrarAsistente(Asistente, Rest, lists:append(Acc, [MapAsistente]))
        end. 
    

    结果:

    #{"abc" => 1,"clave" => a1} == #{"abc" => 1,"clave" => a1}
    #{"abc" => 2,"clave1" => a2} == #{"abc" => 1,"clave" => a1}
    #{"abc" => 3,"clave2" => a3} == #{"abc" => 1,"clave" => a1}
    #{"abc" => 4,"clave3" => a4} == #{"abc" => 1,"clave" => a1}
    [#{"abc" => 2,"clave1" => a2},
     #{"abc" => 3,"clave2" => a3},
     #{"abc" => 4,"clave3" => a4}]
    

    你想这样做吗?

    【讨论】:

    • 如何初始化 Acc?有一个空列表,对吧?
    • server_checaExistenciaBorrarAsistente(Abc, List, [])
    • 按空列表传递 Acc
    • 好吧,这行得通,它实际上是功能性的和递归的,不像其他答案,这对我来说似乎更合适。我做了以下修改虽然pastebin.com/WYfCHE0F
    【解决方案2】:

    一种简单的方法是使用list comprehension 来检查您要查找的密钥是否不存在:

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        [MapAsistente || MapAsistente <- L_Asistentes,
             maps:find("clave", MapAsistente) =/= {ok, Asistente}].
    

    更模块化的方法是允许自定义过滤条件:

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        filter(L_Asistentes, fun(M) -> maps:find("clave", M) =/= {ok, Asistente} end).
    
    filter(Maps, Filter) ->
        [Map || Map <- Maps, Filter(Map)].
    

    【讨论】:

    • 很好的答案,但是这个人显然刚刚开始学习 Erlang,所以无法理解这里发生了什么:)
    • 是的。添加了关于列表推导的 Learn You Some Erlang 章节的链接。
    • 好吧,它成功了。所以让我直截了当。您使用“for”esque 函数来抛出列表并检查每个地图,然后开始比较。现在我不明白的部分是你是如何让它被过滤的。
    • @user3651164, for map in maps include in results list if condition is true 在第一种情况下,maps:find() 函数为条件返回真/假。 , 是一个 if-esque 构造。在第二种情况下,创建结果列表的所有工作都被转移到一个辅助函数,该函数可以命名为get_results()。辅助函数需要两个参数来构造结果:1) 映射列表,2) predicate 函数,如果映射应包含在结果列表中,则该函数接受一个参数并返回 true... .(续)
    • ...在辅助函数中,您具有与第一种情况相同的 list comprehension 结构:for map in maps include in results list if condition is true,这一次 true/false 由 a 返回传递给辅助函数并存储在 Filter 变量中的函数。
    【解决方案3】:
    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        [MapAsistente || MapAsistente <- L_Asistentes,
             maps:find("clave", MapAsistente) =/= {ok, Asistente}].
    

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        filter(L_Asistentes, fun(M) -> maps:find("clave", M) =/= {ok, Asistente} end).
    
    filter(Maps, Filter) ->
        [Map || Map <- Maps, Filter(Map)].
    

    所以让我直说吧。你使用“for”esque 函数去 抛出列表并检查每张地图,然后开始比较。现在 我不明白的部分是你是如何让它被过滤的。

    python 中,列表推导更具可读性:

    results = [Map for Map in Maps if “clave” in Map]
    

    而且,如果你愿意,你可以将 if 条件提取到一个函数中:

    def yes_or_no(Map):
        if 'clave’ in Map:
            return True
        else:
            return False
    
    results = [Map for Map in Maps if yes_or_no(Map)]
    

    请注意,yes_or_no() 接受一个参数并返回 True 或 False。

    这是您想知道的两个erlang examples

    1)

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        [MapAsistente || MapAsistente <- L_Asistentes,
             maps:find("clave", MapAsistente) =/= {ok, Asistente}].
    

    如果您进行这些替换:

    || ... for  
    <- ... in
    ,  ... if
    

    然后你会得到一个 python 列表理解:

    [MapAsistente for MapAsistente in L_Asistentes if
             maps:find("clave", MapAsistente) =/= {ok, Asistente}].
    

    所以你可以看到在 erlang 列表推导中,, 是一个 if-esque 结构。在这种情况下,maps:find() 返回 true/false,这决定了 Map 是否将包含在结果列表中,类似于 python 列表理解中的yes_or_no()

    2)

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        filter(L_Asistentes, fun(M) -> maps:find("clave", M) =/= {ok, Asistente} end).
    
    filter(Maps, Filter) ->
        [Map || Map <- Maps, Filter(Map)].
    

    在这种情况下,不是使用列表推导来计算 server_checaExistenciaBorrarAsistente() 中的结果,而是将创建结果列表的所有工作都转移到一个辅助函数中,该函数可以命名为 get_results():

    server_checaExistenciaBorrarAsistente(Asistente, L_Asistentes) ->
        get_results(...).
    
    get_results(Maps, Filter) ->
        [Map || Map <- Maps, Filter(Map)].
    

    在 python 中,列表解析如下所示:

    [Map for Map in Maps if Filter(Map)]
    

    辅助函数get_results() 需要两个参数来构造结果:

    1. 地图列表。

    2. 一个函数,它接受一个参数并返回 true 或 false 以指示 Map 是否应包含在结果列表中——就像 python yes_or_no() 函数一样。

    get_results() 中,您具有与第一种情况相同的列表理解结构:

    [Map || Map <- Maps, Filter(Map)]
    

    但这一次,真/假由传递给辅助函数并存储在过滤器变量中的函数确定。

    如果有帮助,这里有一个非常简单的例子:

    func() ->
        my_helper(fun lists:reverse/1).
    
    my_helper(SomeFunc) ->
        SomeFunc([1 , 2, 3]).
    

    例子:

    9> c(my).
    {ok,my}
    10> my:func().   
    [3,2,1]
    

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 2014-09-30
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多