【问题标题】:Is there any difference between lists partition and splitwith in Erlang?Erlang中的list partition和splitwith有什么区别吗?
【发布时间】:2016-08-30 10:02:44
【问题描述】:

就像标题一样。 lists:partition/2lists:splitwith/2 都将函数谓词和一个列表作为输入,并生成一个包含两个列表的元组,其中一个谓词返回 true,另一个则谓词返回 false

让我困惑的是最后一句话:

另请参阅(这里是另一个函数)以了解对列表进行分区的不同方式。

如果要给出相同的结果,他们肯定会写这两个函数以相同的方式而不是不同的方式划分列表吗?

【问题讨论】:

    标签: list data-structures functional-programming erlang


    【解决方案1】:

    我觉得源码很清楚。

    partition(Pred, L) ->
        partition(Pred, L, [], []).
    
    partition(Pred, [H | T], As, Bs) ->
        case Pred(H) of
        true -> partition(Pred, T, [H | As], Bs);
        false -> partition(Pred, T, As, [H | Bs])
        end;
    partition(Pred, [], As, Bs) when is_function(Pred, 1) ->
        {reverse(As), reverse(Bs)}.
    

    拆分/2:

    splitwith(Pred, List) when is_function(Pred, 1) ->
        splitwith(Pred, List, []).
    
    splitwith(Pred, [Hd|Tail], Taken) ->
        case Pred(Hd) of
        true -> splitwith(Pred, Tail, [Hd|Taken]);
        false -> {reverse(Taken), [Hd|Tail]}
        end;
    splitwith(Pred, [], Taken) when is_function(Pred, 1) ->
        {reverse(Taken),[]}.
    

    您可以看到splitwith/2 将在Pred 为false 时结束递归。

    【讨论】:

      【解决方案2】:

      对于您的问题 - 是的,这些功能之间存在差异。现在解释一下:

      lists:splitwith/2 的文档中所述

      根据PredList 划分为两个列表。 splitwith/2 行为 好像是这样定义的:

      splitwith(Pred, List) -> {takewhile(Pred, List), dropwhile(Pred, List)}.

      这意味着Pred(Elem)List 的第一个元素开始运行。 Pred(Elem) 返回trueElem 将被添加到第一个列表中。 一旦我们找到Pred(Elem) 返回false 的元素,List 中的其余元素将进入第二个列表。

      相比之下,lists:partition/2List所有 元素上运行Pred(Elem)。如果它为特定元素返回true,它将进入第一个列表,如果它返回false,则该元素将进入第二个列表。它不会在返回 false 的第一个元素上“停止”,例如在 lists:splitwith/2 中。

      让我们看一下除了文档中给出的两个之外的另一个简单示例:

      1> List = [a,b,a,b].
      [a,b,a,b]
      2> Pred = fun(Elem) -> Elem =:= a end.
      #Fun<erl_eval.6.54118792>
      3> lists:partition(Pred,List).
      {[a,a],[b,b]}
      4> lists:splitwith(Pred,List).
      {[a],[b,a,b]}
      

      如我们所见,Pred 函数在Elem =:= a 时返回true

      如果我们运行lists:partition/2,它将遍历所有元素。所以我们在返回的元组的第一个列表中从List 中获取所有等于a 的元素,其余的在第二个列表中。

      如果我们运行lists:splitwith/2,迭代会在到达Pred(Elem) 返回false 的第一个元素时“停止”。在这种情况下,它会停在第二个元素 b 上,并且从这个元素到列表末尾的所有元素都将转到返回元组的第二个列表。

      【讨论】:

      • 哦,对,当然。现在我记得我以前研究过,我得出了同样的结论,然后我又忘记了。感谢您的全面解释!从这个意义上说,splitwithsplit/2 的更智能版本,它只需将指定数量的元素放入第一个列表,然后将其余元素放入第二个列表。
      猜你喜欢
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 1970-01-01
      • 2011-05-04
      • 2020-08-19
      • 2020-06-22
      相关资源
      最近更新 更多