【问题标题】:Erlang list vs tuple comparisonErlang 列表与元组比较
【发布时间】:2012-11-25 18:11:21
【问题描述】:

假设有一个 erlang 列表列表:

请注意,列表的大小是固定的。在这种情况下 3.

A = [[1,2,3],[4,5,6],[1,8,3],[1,9,3]]

我正在尝试编写函数来删除所有[1,_,3] 形式的元素。 所以我的预期输出将是以下形式:[[4,5,6]]

我能想到的一个解决方案是可以使用的列表:dropwhile() 函数。

我在构造谓词函数时遇到问题。将每个元素转换为元组然后进行比较是否更容易?如果是这样,我没有适当的方法可以省略中间元素。

您能帮我找到解决方案吗?任何其他有效的方法也将受到高度赞赏。

提前致谢!

编辑: 问题扩展:

假设有两个erlang列表:

A = [[1,2,3], [2,3,4], [4,5,6]]

B = [[1,4,3], [4,7,6], [7,8,9], [4,9,7], ]

输出 F(A,B) = [[7,8,9], [4,9,7]]

F 被定义为一个函数,它从列表 B 中删除与列表 A 中第一个和第三个位置的任何一个元素匹配的所有元素。

在这种情况下,列表 B 中与 [1, _ ,3] 或 [2, _ , 4] 或 [4 , _ , 6] 匹配的所有元素都将从列表中删除以给出结果列表。

我正在努力写 F。

【问题讨论】:

  • 到目前为止,您的谓词函数是什么样的?我想你会发现元组或列表非常相似。
  • 到目前为止我最大的努力是,lists:filter(fun(X) -> {1,_,3} == erlang:list_to_tuple(X) end,A)。但是我收到了一个 _ unbound variable 错误。单个等于 (=) 仅在其为 false 时分配给变量,并且不返回 true 或 false。

标签: functional-programming erlang


【解决方案1】:

我设法为扩展问题想出了一个解决方案:

给定 A 和 B:

F(A,B) ->
    lists:filter(fun(X) -> predicate(X,B) end, A).

predicate(X, B) ->
    Xr = lists:delete(lists:nth(2,X),X),
    Br = lists:map(lists:delete(lists:nth(2,Y),Y),B),
    lists:member(Xr, Br).

这个列表库太酷了.. :)

【讨论】:

    【解决方案2】:

    您的过滤功能需要一些帮助:

    lists:filter(fun([1, _, 3]) -> false; (_) -> true end,
                 [[1,2,3],[4,5,6],[1,8,3],[1,9,3]]).
    

    你需要函数头中的匹配来完成这项工作。


    至于有多个过滤器,你可以使用一张有趣的地图(未测试):

    composed_filter(Tests, Input) ->
      lists:filter(fun(X) -> lists:all([F(X) || F <- Tests]) end,
                   Input).
    

    对于使用多个过滤器,您可以这样做:

    filter(fun([1,_,3]) -> true;
              ([5,_,7]) -> true;
              ([9,_,13]) -> true;
              (_) -> false end, Input)
    % or
    composed_filter([fun([1,_,3]) -> true; (_) -> false end,
                     fun([5,_,7]) -> true; (_) -> false end,
                     fun([9,_,13]) -> true; (_) -> false end],
                    Input)
    

    尽管除非您需要可编程动态可组合性,否则您可能应该只使用第一个。另一种方法是使用函数而不是专门的composer_filter来运行组合。这是 Haskell 人群会喜欢的更加组合器风格的方法。请注意,上述功能略有不同。第一个具有orelse 语义,而后者具有andalso 语义。也就是说,在第一种情况下,如果一个或多个模式匹配,您就会得到元素,而在后一种情况下,只有 all 模式/乐趣匹配时才会得到结果。您可以使用lists:any/2 获取composed_any_filter

    【讨论】:

    • 同一个过滤函数中是否可以有两个谓词?在那种情况下,函数头会是一团糟,对吧?我能想到的唯一方法是让列表通过上面定义的两个顺序过滤器。但我想这不会使其扩展以拥有任何新的附加谓词......
    • 通过一种解决方案添加到答案中。还有更多这样的解决方案,包括两次遍历列表。这可能会产生开销,但这取决于您尝试步行的列表。
    • 这是一个优雅的解决方案。但是我们怎么会有一个函数列表。假设对于问题中定义的相同问题,如果我们不仅要比较 [1,,3].. 还要比较 [1,,5],[7,_9] 等等在。那时建议将所有这些都写在一个过滤器中?
    • 感谢您的解决方案。我可能应该尝试其他方法,但我的问题略有扩展,如果您能对此有所了解,那就太好了。
    • 如果我的编辑没有说清楚,请再次访问。我不确定我是否了解您在寻找什么?
    【解决方案3】:

    dropWhile 只能返回列表的前缀,所以它不起作用。请改用filter

    【讨论】:

    • 感谢您的提示。我终于明白了其中的区别。
    猜你喜欢
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2017-09-01
    相关资源
    最近更新 更多