【问题标题】:Executing a function on a list and a list of lists (Erlang)在列表和列表列表上执行函数(Erlang)
【发布时间】:2015-02-01 01:51:49
【问题描述】:

我有两个列表:

Category_list = [a, b, c, d]
Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

对于 Category_list 中的每个元素和 Id_list 中第一个列表中的每个元素,我想执行一个函数。想象一下我有这个功能:

Check_id(Category, ID)

因此我需要一个可以像这样运行 check_id 的函数(但实际上需要更多的 ID):

Check_id(a, 1), Check_id(a, 2), Check_id(a, 3), Check_id(a, 4),
Check_id(b, 5), Check_id(b, 6), Check_id(b, 7), Check_id(b, 8),
Check_id(c, 9), Check_id(c, 10), Check_id(c, 11), Check_id(c, 12),
Check_id(d, 13), Check_id(d, 14), Check_id(d, 15), Check_id(d, 16).

Category_list 中的元素数量和 ID_list 中的元素(列表)数量将始终相同。我已经尝试使用列表推导以及“lists:foreach”有一段时间了,但无济于事。

【问题讨论】:

    标签: list foreach erlang list-comprehension nested-lists


    【解决方案1】:

    我同意,您应该使用PascalCase,这是首字母大写的驼峰式大小写。不过,我不会费心添加人工索引。

    -module(category).
    
    -compile([export_all]).
    
    run() ->
        Category_list = [a, b, c, d],
        Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]],
        Zipped = lists:zip(Category_list, Id_list),
        [check_categories(Category, List) || {Category, List} <- Zipped].
    
    check_categories(Category, List) ->
        [check_category(Category, Element) || Element <- List].
    
    check_category(Category, Element) ->
        io:format("~p ~p~n", [Category, Element]).
    

    lists:zip/2 接受两个列表并将它们合并到元组列表中:

    [{a,[1,2,3,4]},{b,[5,6,7,8]},{c,"\t\n\v\f"},{d,[13,14,15,16]}]
    

    然后,您可以使用 {Category, ListOfElementsWithThisCategory} 快速扫描元组。

    【讨论】:

      【解决方案2】:
      check_id(C, Id) ->
          {C, Id}.
      
      main()->
          Category_list = [a, b, c, d],
          Id_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]],
      
          Zip = lists:zip(Category_list, Id_list),
          Res = lists:map(fun({C, Ids}) -> [check_id(C, Id) || Id <- Ids] end, Zip),
          lists:flatten(Res).
      

      你可以试试这个方法,输出是:

      [{a,1},
       {a,2},
       {a,3},
       {a,4},
       {b,5},
       {b,6},
       {b,7},
       {b,8},
       {c,9},
       {c,10},
       {c,11},
       {c,12},
       {d,13},
       {d,14},
       {d,15},
       {d,16}]
      

      【讨论】:

        【解决方案3】:

        这是没有索引的 O(n) 解决方案

        lists:foldl(
            fun (Category, [Ids | Id_listTail]) -> 
                lists:foreach(
                    fun (Id) -> 
                        Check_id(Category, Id) 
                    end, Ids),
                Id_listTail
            end, Id_list, Category_list),
        

        这个列表理解也应该对你有用:

        %% note it's O(n^2) solution. Don't use it if Category list is much longer than in example:
        [Check_id(lists:nth(N,Category_list), Id) || 
            N <-lists:seq(1,length(Category_list)), 
            Id <- lists:nth(N,Id_list)].
        

        顺便说一句,使用PascalCase 命名所谓的“变量”是一种常见的做法:

        Check_id => CheckId
        Category_list => CategoryList
        Id_list => IdList
        

        【讨论】:

        • 您可以通过命名匿名函数并将内部函数移出 foreach 来提高可读性。好的 Erlang 代码最多嵌套两次。一次,因为您在函数内部编写,第二次在接收语句内部编写 :) 这可能是极端的,但我通常太愚蠢而无法理解更多嵌套代码。使用foldl 确实是个好主意,因为您没有创建辅助列表。
        • 嵌套 foldl 和 foreach 的可读性问题来自我相信的参数序列,这就是为什么我写了我们前段时间讨论过的函数 - 以更自然的方式编写并提高可读性;)我真的很喜欢使用闭包。它有助于使模块更简单。
        【解决方案4】:

        列表推导接受一个函数、一个类别列表和一个 id 的子列表列表并执行所有检查。它不会对列表和子列表大小带来任何限制(除非是合理的:o)。我添加了一个 lists:flatten/1 来呈现结果,但是如果您不需要收集结果,它可能没用。

        1> Check_id = fun(Cat,Id) -> {Cat,Id} end.
        #Fun<erl_eval.12.90072148>
        2> CatList = [a,b,c].
        [a,b,c]
        3> IdList = [[1,2,3],[4,5,6]].
        [[1,2,3],[4,5,6]]
        4> lists:flatten([[Check_id(Cat,Id) || Cat <- CatList, Id <- SubIdList] || SubIdList <- IdList]).
        [{a,1},
         {a,2},
         {a,3},
         {b,1},
         {b,2},
         {b,3},
         {c,1},
         {c,2},
         {c,3},
         {a,4},
         {a,5},
         {a,6},
         {b,4},
         {b,5},
         {b,6},
         {c,4},
         {c,5},
         {c,6}]
        5>
        

        【讨论】:

          猜你喜欢
          • 2016-08-25
          • 2015-04-22
          • 1970-01-01
          • 2010-11-30
          • 2015-04-29
          • 2018-04-10
          • 2015-02-12
          • 2013-05-27
          • 1970-01-01
          相关资源
          最近更新 更多